diff --git a/packages/trace-viewer/src/ui/networkResourceDetails.css b/packages/trace-viewer/src/ui/networkResourceDetails.css
index 9310a6c553894..fff88aa577f5e 100644
--- a/packages/trace-viewer/src/ui/networkResourceDetails.css
+++ b/packages/trace-viewer/src/ui/networkResourceDetails.css
@@ -23,20 +23,9 @@
flex: none;
}
-.network-request-details-url {
- white-space: normal;
- word-wrap: break-word;
- margin-left: 10px;
-}
-
-.network-request-details-headers {
- white-space: pre;
- overflow: hidden;
- margin-left: 10px;
-}
-
.network-request-details-tab .expandable-title {
padding-left: 3px;
+ background-color: var(--vscode-sideBar-background);
}
.network-request-details-tab .expandable-content {
@@ -50,9 +39,22 @@
font-weight: bold;
}
-.network-request-details-general {
- white-space: pre;
- margin-left: 10px;
+.network-request-details-table {
+ width: 100%;
+ line-height: 18px;
+ padding: 8px 0 8px 8px;
+ white-space: pre-wrap;
+}
+
+.network-request-details-table td:first-of-type {
+ width: 30%;
+ min-width: 160px;
+ vertical-align: top;
+}
+
+.network-request-details-table td:nth-of-type(2) {
+ word-break: break-all;
+ vertical-align: center;
}
.network-request-details-tab .cm-wrapper {
diff --git a/packages/trace-viewer/src/ui/networkResourceDetails.tsx b/packages/trace-viewer/src/ui/networkResourceDetails.tsx
index 50f4a9eb42340..cab1d9c3e212a 100644
--- a/packages/trace-viewer/src/ui/networkResourceDetails.tsx
+++ b/packages/trace-viewer/src/ui/networkResourceDetails.tsx
@@ -108,9 +108,10 @@ const CopyDropdown: React.FC<{
const ExpandableSection: React.FC<{
title: string;
+ data?: { name: string, value: React.ReactNode }[],
children?: React.ReactNode
className?: string;
-}> = ({ title, children, className }) => {
+}> = ({ title, data, children, className }) => {
const [expanded, setExpanded] = useSetting(`trace-viewer-network-details-${title.replaceAll(' ', '-')}`, true);
return {title}}
className={className}
>
+ {data &&
+
+ {data.map(({ name, value }, index) => (
+ value !== null &&
+ (
+ | {name} |
+ {value} |
+
)
+ ))}
+
+
}
{children}
;
};
@@ -128,33 +140,26 @@ const RequestTab: React.FunctionComponent<{
startTimeOffset: number;
requestBody: RequestBody,
}> = ({ resource, startTimeOffset, requestBody }) => {
- return
-
- {`URL: ${resource.request.url}`}
- {`Method: ${resource.request.method}`}
- {resource.response.status !== -1 &&
- Status Code:
- {`${resource.response.status} ${resource.response.statusText}`}
-
}
-
-
- {resource.request.queryString.length ?
-
-
- {resource.request.queryString.map(param => `${param.name}: ${param.value}`).join('\n')}
-
-
- : null}
+ const generalData = React.useMemo(() =>
+ Object.entries({
+ 'URL': resource.request.url,
+ 'Method': resource.request.method,
+ 'Status Code': resource.response.status !== -1 &&
{resource.response.status} {resource.response.statusText},
+ }).map(([name, value]) => ({ name, value })),
+ [resource]);
-
- {resource.request.headers.map(pair => `${pair.name}: ${pair.value}`).join('\n')}
-
-
-
- {`Start: ${msToString(startTimeOffset)}`}
- {`Duration: ${msToString(resource.time)}`}
-
+ const timeData = React.useMemo(() =>
+ Object.entries({
+ 'Start': msToString(startTimeOffset),
+ 'Duration': msToString(resource.time),
+ }).map(([name, value]) => ({ name, value })),
+ [startTimeOffset, resource]);
+ return
+
+ {resource.request.queryString.length > 0 && }
+
+
{requestBody &&
}
@@ -165,9 +170,7 @@ const ResponseTab: React.FunctionComponent<{
resource: ResourceSnapshot;
}> = ({ resource }) => {
return
-
- {resource.response.headers.map(pair => `${pair.name}: ${pair.value}`).join('\n')}
-
+
;
};
diff --git a/tests/playwright-test/ui-mode-test-network-tab.spec.ts b/tests/playwright-test/ui-mode-test-network-tab.spec.ts
index c0fb4669c6f81..0e7014b5e76a6 100644
--- a/tests/playwright-test/ui-mode-test-network-tab.spec.ts
+++ b/tests/playwright-test/ui-mode-test-network-tab.spec.ts
@@ -197,9 +197,14 @@ test('should display list of query parameters (only if present)', async ({ runUI
await page.getByText('call-with-query-params').click();
const region = page.getByRole('region', { name: 'Query String Parameters' });
- await expect(region.getByText('param1: value1')).toBeVisible();
- await expect(region.getByText('param1: value2')).toBeVisible();
- await expect(region.getByText('param2: value2')).toBeVisible();
+ await expect(region).toMatchAriaSnapshot(
+ `- table:
+ - rowgroup:
+ - 'row "param1 value1"'
+ - 'row "param1 value2"'
+ - 'row "param2 value2"'
+ `
+ );
await page.getByText('endpoint').click();
@@ -260,7 +265,7 @@ test('should toggle sections inside network details', async ({ runUITest, server
await requestPanel.getByRole('button', { name: 'Request Headers' }).click();
await expect(requestPanel.getByRole('region', { name: 'Request Headers' })).toBeHidden();
- await expect(requestPanel.getByRole('region', { name: 'Time' })).toHaveText(/Start: .+Duration: \d+ms/);
+ await expect(requestPanel.getByRole('region', { name: 'Time' })).toHaveText(/Start.+Duration\d+ms/);
await requestPanel.getByRole('button', { name: 'Time' }).click();
await expect(requestPanel.getByRole('region', { name: 'Request Headers' })).toBeHidden();
@@ -268,11 +273,11 @@ test('should toggle sections inside network details', async ({ runUITest, server
await requestPanel.getByRole('button', { name: 'Time' }).click();
await expect(requestPanel.getByRole('region', { name: 'Request Headers' })).toBeHidden();
- await expect(requestPanel.getByRole('region', { name: 'Time' })).toHaveText(/Start: .+Duration: \d+ms/);
+ await expect(requestPanel.getByRole('region', { name: 'Time' })).toHaveText(/Start.+Duration\d+ms/);
// Re-opening should preserve open state
await page.getByRole('tabpanel', { name: 'Network' }).getByRole('button', { name: 'Close' }).click();
await page.getByRole('listitem').filter({ hasText: 'post-data-1' }).click();
await expect(requestPanel.getByRole('region', { name: 'Request Headers' })).toBeHidden();
- await expect(requestPanel.getByRole('region', { name: 'Time' })).toHaveText(/Start: .+Duration: \d+ms/);
+ await expect(requestPanel.getByRole('region', { name: 'Time' })).toHaveText(/Start.+Duration\d+ms/);
});