From d13736d17ecdc1d99a194fa3a85e9e7437c839fc Mon Sep 17 00:00:00 2001 From: Adam Gastineau Date: Mon, 9 Dec 2024 12:01:01 -0800 Subject: [PATCH 1/7] feat: Add startTime to call tab --- packages/trace-viewer/src/ui/callTab.tsx | 20 +++++++++++++++----- packages/trace-viewer/src/ui/workbench.tsx | 2 +- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/trace-viewer/src/ui/callTab.tsx b/packages/trace-viewer/src/ui/callTab.tsx index 1ab3b5b46f4b9..cfa3be4880a72 100644 --- a/packages/trace-viewer/src/ui/callTab.tsx +++ b/packages/trace-viewer/src/ui/callTab.tsx @@ -27,24 +27,32 @@ import type { ActionTraceEventInContext } from './modelUtil'; export const CallTab: React.FunctionComponent<{ action: ActionTraceEventInContext | undefined, + executionStartTime: number, + executionStartWallTime: number, sdkLanguage: Language | undefined, -}> = ({ action, sdkLanguage }) => { +}> = ({ action, executionStartTime, executionStartWallTime, sdkLanguage }) => { if (!action) return ; const params = { ...action.params }; // Strip down the waitForEventInfo data, we never need it. delete params.info; const paramKeys = Object.keys(params); - const timeMillis = action.startTime + (action.context.wallTime - action.context.startTime); - const wallTime = new Date(timeMillis).toLocaleString(); + + const startTimeMillis = action.startTime - executionStartTime; + const startTime = msToString(startTimeMillis); + + const wallTimeMillis = startTimeMillis + executionStartWallTime; + const wallTime = new Date(wallTimeMillis).toLocaleString(); + const duration = action.endTime ? msToString(action.endTime - action.startTime) : 'Timed Out'; return
{action.apiName}
{<>
Time
- {wallTime &&
wall time:{wallTime}
} -
duration:{duration}
+ {wallTime && } + + } { !!paramKeys.length &&
Parameters
} { @@ -59,6 +67,8 @@ export const CallTab: React.FunctionComponent<{
; }; +const DateTimeCallLine: React.FC<{ name: string, value: string }> = ({ name, value }) =>
{name}{value}
; + type Property = { name: string; type: 'string' | 'number' | 'object' | 'locator' | 'handle' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'function'; diff --git a/packages/trace-viewer/src/ui/workbench.tsx b/packages/trace-viewer/src/ui/workbench.tsx index ad8a099ea4fde..a705b71ef9ab2 100644 --- a/packages/trace-viewer/src/ui/workbench.tsx +++ b/packages/trace-viewer/src/ui/workbench.tsx @@ -176,7 +176,7 @@ export const Workbench: React.FunctionComponent<{ const callTab: TabbedPaneTabModel = { id: 'call', title: 'Call', - render: () => + render: () => }; const logTab: TabbedPaneTabModel = { id: 'log', From ef78bc69bb302eaae3fab27013117723ce525d2f Mon Sep 17 00:00:00 2001 From: Adam Gastineau Date: Mon, 9 Dec 2024 12:15:53 -0800 Subject: [PATCH 2/7] Cleaned up callTab React code --- packages/trace-viewer/src/ui/callTab.tsx | 57 +++++++++++++----------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/packages/trace-viewer/src/ui/callTab.tsx b/packages/trace-viewer/src/ui/callTab.tsx index cfa3be4880a72..fcbf9b6307ce3 100644 --- a/packages/trace-viewer/src/ui/callTab.tsx +++ b/packages/trace-viewer/src/ui/callTab.tsx @@ -31,12 +31,11 @@ export const CallTab: React.FunctionComponent<{ executionStartWallTime: number, sdkLanguage: Language | undefined, }> = ({ action, executionStartTime, executionStartWallTime, sdkLanguage }) => { + // We never need the waitForEventInfo (`info`). + const paramKeys = React.useMemo(() => Object.keys(action?.params ?? {}).filter(name => name !== 'info'), [action]); + if (!action) return ; - const params = { ...action.params }; - // Strip down the waitForEventInfo data, we never need it. - delete params.info; - const paramKeys = Object.keys(params); const startTimeMillis = action.startTime - executionStartTime; const startTime = msToString(startTimeMillis); @@ -46,25 +45,33 @@ export const CallTab: React.FunctionComponent<{ const duration = action.endTime ? msToString(action.endTime - action.startTime) : 'Timed Out'; - return
-
{action.apiName}
- {<> -
Time
- {wallTime && } - - - } - { !!paramKeys.length &&
Parameters
} - { - !!paramKeys.length && paramKeys.map((name, index) => renderProperty(propertyToString(action, name, params[name], sdkLanguage), 'param-' + index)) - } - { !!action.result &&
Return value
} - { - !!action.result && Object.keys(action.result).map((name, index) => - renderProperty(propertyToString(action, name, action.result[name], sdkLanguage), 'result-' + index) - ) - } -
; + return ( +
+
{action.apiName}
+ { + <> +
Time
+ {wallTime && } + + + + } + { + !!paramKeys.length && <> +
Parameters
+ {paramKeys.map(name => renderProperty(propertyToString(action, name, action.params[name], sdkLanguage)))} + + } + { + !!action.result && <> +
Return value
+ {Object.keys(action.result).map(name => + renderProperty(propertyToString(action, name, action.result[name], sdkLanguage)) + )} + + } +
+ ); }; const DateTimeCallLine: React.FC<{ name: string, value: string }> = ({ name, value }) =>
{name}{value}
; @@ -75,12 +82,12 @@ type Property = { text: string; }; -function renderProperty(property: Property, key: string) { +function renderProperty(property: Property) { let text = property.text.replace(/\n/g, '↵'); if (property.type === 'string') text = `"${text}"`; return ( -
+
{property.name}:{text} { ['string', 'number', 'object', 'locator'].includes(property.type) && From d022d7727ee60402cfa6137395e3c5f4f4217dba Mon Sep 17 00:00:00 2001 From: Adam Gastineau Date: Tue, 10 Dec 2024 09:46:20 -0800 Subject: [PATCH 3/7] Time support in Network details tab --- packages/trace-viewer/src/ui/callTab.tsx | 3 ++- packages/trace-viewer/src/ui/metadataView.tsx | 4 +++- .../src/ui/networkResourceDetails.tsx | 17 +++++++++++++---- packages/trace-viewer/src/ui/networkTab.tsx | 2 +- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/packages/trace-viewer/src/ui/callTab.tsx b/packages/trace-viewer/src/ui/callTab.tsx index fcbf9b6307ce3..137c4d22d9de8 100644 --- a/packages/trace-viewer/src/ui/callTab.tsx +++ b/packages/trace-viewer/src/ui/callTab.tsx @@ -37,11 +37,12 @@ export const CallTab: React.FunctionComponent<{ if (!action) return ; + // Calculate execution time relative to the test runner's start time const startTimeMillis = action.startTime - executionStartTime; const startTime = msToString(startTimeMillis); const wallTimeMillis = startTimeMillis + executionStartWallTime; - const wallTime = new Date(wallTimeMillis).toLocaleString(); + const wallTime = new Date(wallTimeMillis).toLocaleString(undefined, { timeZoneName: 'short' }); const duration = action.endTime ? msToString(action.endTime - action.startTime) : 'Timed Out'; diff --git a/packages/trace-viewer/src/ui/metadataView.tsx b/packages/trace-viewer/src/ui/metadataView.tsx index c1802a4b4d78c..88c2e2bf933fd 100644 --- a/packages/trace-viewer/src/ui/metadataView.tsx +++ b/packages/trace-viewer/src/ui/metadataView.tsx @@ -25,9 +25,11 @@ export const MetadataView: React.FunctionComponent<{ if (!model) return <>; + const wallTime = model.wallTime !== undefined ? new Date(model.wallTime).toLocaleString(undefined, { timeZoneName: 'short' }) : undefined; + return
Time
- {!!model.wallTime &&
start time:{new Date(model.wallTime).toLocaleString()}
} + {!!wallTime &&
start time:{wallTime}
}
duration:{msToString(model.endTime - model.startTime)}
Browser
engine:{model.browserName}
diff --git a/packages/trace-viewer/src/ui/networkResourceDetails.tsx b/packages/trace-viewer/src/ui/networkResourceDetails.tsx index 9805d42c6f3e2..e3e3a80538fe7 100644 --- a/packages/trace-viewer/src/ui/networkResourceDetails.tsx +++ b/packages/trace-viewer/src/ui/networkResourceDetails.tsx @@ -24,12 +24,14 @@ import { generateCurlCommand, generateFetchCall } from '../third_party/devtools' import { CopyToClipboardTextButton } from './copyToClipboard'; import { getAPIRequestCodeGen } from './codegen'; import type { Language } from '@isomorphic/locatorGenerators'; +import { msToString } from '@web/uiUtils'; export const NetworkResourceDetails: React.FunctionComponent<{ resource: ResourceSnapshot; - onClose: () => void; sdkLanguage: Language; -}> = ({ resource, onClose, sdkLanguage }) => { + startTimeOffset: number; + onClose: () => void; +}> = ({ resource, sdkLanguage, startTimeOffset, onClose }) => { const [selectedTab, setSelectedTab] = React.useState('request'); return , + render: () => , }, { id: 'response', @@ -59,9 +61,12 @@ export const NetworkResourceDetails: React.FunctionComponent<{ const RequestTab: React.FunctionComponent<{ resource: ResourceSnapshot; sdkLanguage: Language; -}> = ({ resource, sdkLanguage }) => { + startTimeOffset: number; +}> = ({ resource, sdkLanguage, startTimeOffset }) => { const [requestBody, setRequestBody] = React.useState<{ text: string, mimeType?: string } | null>(null); + const wallTimeString = React.useMemo(() => resource.startedDateTime.length > 0 ? new Date(resource.startedDateTime).toLocaleString(undefined, { timeZoneName: 'short' }) : '-', [resource.startedDateTime]); + React.useEffect(() => { const readResources = async () => { if (resource.request.postData) { @@ -94,6 +99,10 @@ const RequestTab: React.FunctionComponent<{ {resource.request.queryString.map(param => `${param.name}: ${param.value}`).join('\n')}
: null} +
Time
+
{`Wall Time: ${wallTimeString}`}
+
{`Start: ${msToString(startTimeOffset)}`}
+
{`Duration: ${msToString(resource.time)}`}
Request Headers
{resource.request.headers.map(pair => `${pair.name}: ${pair.value}`).join('\n')}
diff --git a/packages/trace-viewer/src/ui/networkTab.tsx b/packages/trace-viewer/src/ui/networkTab.tsx index 56cf9325b479b..ceaafdcec52cf 100644 --- a/packages/trace-viewer/src/ui/networkTab.tsx +++ b/packages/trace-viewer/src/ui/networkTab.tsx @@ -117,7 +117,7 @@ export const NetworkTab: React.FunctionComponent<{ sidebarIsFirst={true} orientation='horizontal' settingName='networkResourceDetails' - main={ setSelectedEntry(undefined)} sdkLanguage={sdkLanguage} />} + main={ setSelectedEntry(undefined)} />} sidebar={grid} />} ; From 2b24d05abd7035da8828109051e2eb774a86cab2 Mon Sep 17 00:00:00 2001 From: Adam Gastineau Date: Tue, 10 Dec 2024 12:21:02 -0800 Subject: [PATCH 4/7] Fix tests that check call tab contents --- tests/library/trace-viewer.spec.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/library/trace-viewer.spec.ts b/tests/library/trace-viewer.spec.ts index 2bd7b858880d6..e834af37cfb29 100644 --- a/tests/library/trace-viewer.spec.ts +++ b/tests/library/trace-viewer.spec.ts @@ -241,6 +241,7 @@ test('should show params and return value', async ({ showTraceViewer }) => { await expect(traceViewer.callLines).toHaveText([ /page.evaluate/, /wall time:[0-9/:,APM ]+/, + /start:[\d\.]+m?s/, /duration:[\d]+ms/, /expression:"\({↵ a↵ }\) => {↵ console\.log\(\'Info\'\);↵ console\.warn\(\'Warning\'\);↵ console/, 'isFunction:true', @@ -252,6 +253,7 @@ test('should show params and return value', async ({ showTraceViewer }) => { await expect(traceViewer.callLines).toContainText([ /expect.toHaveText/, /wall time:[0-9/:,APM ]+/, + /start:[\d\.]+m?s/, /duration:[\d]+ms/, /locator:locator\('button'\)/, /expression:"to.have.text"/, @@ -267,6 +269,7 @@ test('should show null as a param', async ({ showTraceViewer, browserName }) => await expect(traceViewer.callLines).toHaveText([ /page.evaluate/, /wall time:[0-9/:,APM ]+/, + /start:[\d\.]+m?s/, /duration:[\d]+ms/, 'expression:"() => 1 + 1"', 'isFunction:true', From 4bdd625d0446c28ffaa206f13fbcea9b830541e7 Mon Sep 17 00:00:00 2001 From: Adam Gastineau Date: Wed, 18 Dec 2024 12:49:08 -0800 Subject: [PATCH 5/7] Address PR comments --- packages/trace-viewer/src/ui/callTab.tsx | 6 +++--- packages/trace-viewer/src/ui/networkResourceDetails.tsx | 4 ++-- packages/trace-viewer/src/ui/workbench.tsx | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/trace-viewer/src/ui/callTab.tsx b/packages/trace-viewer/src/ui/callTab.tsx index 137c4d22d9de8..6c1547a9a3f36 100644 --- a/packages/trace-viewer/src/ui/callTab.tsx +++ b/packages/trace-viewer/src/ui/callTab.tsx @@ -52,9 +52,9 @@ export const CallTab: React.FunctionComponent<{ { <>
Time
- {wallTime && } - - + + + } { diff --git a/packages/trace-viewer/src/ui/networkResourceDetails.tsx b/packages/trace-viewer/src/ui/networkResourceDetails.tsx index 22667c95dba1f..f39fe9127fdff 100644 --- a/packages/trace-viewer/src/ui/networkResourceDetails.tsx +++ b/packages/trace-viewer/src/ui/networkResourceDetails.tsx @@ -99,12 +99,12 @@ const RequestTab: React.FunctionComponent<{ {resource.request.queryString.map(param => `${param.name}: ${param.value}`).join('\n')}
: null} +
Request Headers
+
{resource.request.headers.map(pair => `${pair.name}: ${pair.value}`).join('\n')}
Time
{`Wall Time: ${wallTimeString}`}
{`Start: ${msToString(startTimeOffset)}`}
{`Duration: ${msToString(resource.time)}`}
-
Request Headers
-
{resource.request.headers.map(pair => `${pair.name}: ${pair.value}`).join('\n')}
generateCurlCommand(resource)} /> diff --git a/packages/trace-viewer/src/ui/workbench.tsx b/packages/trace-viewer/src/ui/workbench.tsx index a705b71ef9ab2..deb325d271ece 100644 --- a/packages/trace-viewer/src/ui/workbench.tsx +++ b/packages/trace-viewer/src/ui/workbench.tsx @@ -176,7 +176,7 @@ export const Workbench: React.FunctionComponent<{ const callTab: TabbedPaneTabModel = { id: 'call', title: 'Call', - render: () => + render: () => }; const logTab: TabbedPaneTabModel = { id: 'log', From 50c6ea3aaf580c1a414a187f4782855bb862c604 Mon Sep 17 00:00:00 2001 From: Adam Gastineau Date: Thu, 19 Dec 2024 12:39:06 -0800 Subject: [PATCH 6/7] Remove error-prone wall time --- packages/trace-viewer/src/ui/callTab.tsx | 11 +++-------- .../trace-viewer/src/ui/networkResourceDetails.tsx | 3 --- packages/trace-viewer/src/ui/workbench.tsx | 2 +- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/packages/trace-viewer/src/ui/callTab.tsx b/packages/trace-viewer/src/ui/callTab.tsx index 6c1547a9a3f36..1c78920f86e0f 100644 --- a/packages/trace-viewer/src/ui/callTab.tsx +++ b/packages/trace-viewer/src/ui/callTab.tsx @@ -27,10 +27,9 @@ import type { ActionTraceEventInContext } from './modelUtil'; export const CallTab: React.FunctionComponent<{ action: ActionTraceEventInContext | undefined, - executionStartTime: number, - executionStartWallTime: number, + startTimeOffset: number, sdkLanguage: Language | undefined, -}> = ({ action, executionStartTime, executionStartWallTime, sdkLanguage }) => { +}> = ({ action, startTimeOffset, sdkLanguage }) => { // We never need the waitForEventInfo (`info`). const paramKeys = React.useMemo(() => Object.keys(action?.params ?? {}).filter(name => name !== 'info'), [action]); @@ -38,12 +37,9 @@ export const CallTab: React.FunctionComponent<{ return ; // Calculate execution time relative to the test runner's start time - const startTimeMillis = action.startTime - executionStartTime; + const startTimeMillis = action.startTime - startTimeOffset; const startTime = msToString(startTimeMillis); - const wallTimeMillis = startTimeMillis + executionStartWallTime; - const wallTime = new Date(wallTimeMillis).toLocaleString(undefined, { timeZoneName: 'short' }); - const duration = action.endTime ? msToString(action.endTime - action.startTime) : 'Timed Out'; return ( @@ -52,7 +48,6 @@ export const CallTab: React.FunctionComponent<{ { <>
Time
- diff --git a/packages/trace-viewer/src/ui/networkResourceDetails.tsx b/packages/trace-viewer/src/ui/networkResourceDetails.tsx index f39fe9127fdff..aaa78d17860a0 100644 --- a/packages/trace-viewer/src/ui/networkResourceDetails.tsx +++ b/packages/trace-viewer/src/ui/networkResourceDetails.tsx @@ -65,8 +65,6 @@ const RequestTab: React.FunctionComponent<{ }> = ({ resource, sdkLanguage, startTimeOffset }) => { const [requestBody, setRequestBody] = React.useState<{ text: string, mimeType?: string } | null>(null); - const wallTimeString = React.useMemo(() => resource.startedDateTime.length > 0 ? new Date(resource.startedDateTime).toLocaleString(undefined, { timeZoneName: 'short' }) : '-', [resource.startedDateTime]); - React.useEffect(() => { const readResources = async () => { if (resource.request.postData) { @@ -102,7 +100,6 @@ const RequestTab: React.FunctionComponent<{
Request Headers
{resource.request.headers.map(pair => `${pair.name}: ${pair.value}`).join('\n')}
Time
-
{`Wall Time: ${wallTimeString}`}
{`Start: ${msToString(startTimeOffset)}`}
{`Duration: ${msToString(resource.time)}`}
diff --git a/packages/trace-viewer/src/ui/workbench.tsx b/packages/trace-viewer/src/ui/workbench.tsx index deb325d271ece..7a14d495c69a6 100644 --- a/packages/trace-viewer/src/ui/workbench.tsx +++ b/packages/trace-viewer/src/ui/workbench.tsx @@ -176,7 +176,7 @@ export const Workbench: React.FunctionComponent<{ const callTab: TabbedPaneTabModel = { id: 'call', title: 'Call', - render: () => + render: () => }; const logTab: TabbedPaneTabModel = { id: 'log', From bd55d5d8ff66f72a1d2a814ce18504d504d56839 Mon Sep 17 00:00:00 2001 From: Adam Gastineau Date: Thu, 19 Dec 2024 12:41:25 -0800 Subject: [PATCH 7/7] Removed test reference to wall time --- tests/library/trace-viewer.spec.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/library/trace-viewer.spec.ts b/tests/library/trace-viewer.spec.ts index 024d5beb868c9..53c6bcf6c4497 100644 --- a/tests/library/trace-viewer.spec.ts +++ b/tests/library/trace-viewer.spec.ts @@ -240,7 +240,6 @@ test('should show params and return value', async ({ showTraceViewer }) => { await traceViewer.selectAction('page.evaluate'); await expect(traceViewer.callLines).toHaveText([ /page.evaluate/, - /wall time:[0-9/:,APM ]+/, /start:[\d\.]+m?s/, /duration:[\d]+ms/, /expression:"\({↵ a↵ }\) => {↵ console\.log\(\'Info\'\);↵ console\.warn\(\'Warning\'\);↵ console/, @@ -252,7 +251,6 @@ test('should show params and return value', async ({ showTraceViewer }) => { await traceViewer.selectAction(`locator('button')`); await expect(traceViewer.callLines).toContainText([ /expect.toHaveText/, - /wall time:[0-9/:,APM ]+/, /start:[\d\.]+m?s/, /duration:[\d]+ms/, /locator:locator\('button'\)/, @@ -268,7 +266,6 @@ test('should show null as a param', async ({ showTraceViewer, browserName }) => await traceViewer.selectAction('page.evaluate', 1); await expect(traceViewer.callLines).toHaveText([ /page.evaluate/, - /wall time:[0-9/:,APM ]+/, /start:[\d\.]+m?s/, /duration:[\d]+ms/, 'expression:"() => 1 + 1"',