From 39efc67cb904eb26992ca128e85d2f5be8ff3c73 Mon Sep 17 00:00:00 2001 From: scs0209 <110822847+scs0209@users.noreply.github.com> Date: Mon, 31 Aug 2026 09:33:51 +0900 Subject: [PATCH 1/2] fix(trace-viewer): label filter inputs and keyboard-accessible error source Add aria-labels to the network and UI mode filter searchboxes, and replace the mouse-only error source span with a native button that exposes an accessible name and focus ring. Closes #42463 Co-authored-by: Cursor --- packages/trace-viewer/src/ui/actionList.css | 12 ++++++++++- packages/trace-viewer/src/ui/errorsTab.tsx | 2 +- .../trace-viewer/src/ui/networkFilters.tsx | 1 + .../trace-viewer/src/ui/uiModeFiltersView.tsx | 2 +- tests/library/trace-viewer.spec.ts | 20 +++++++++++++++++++ .../ui-mode-test-filters.spec.ts | 6 ++++++ 6 files changed, 40 insertions(+), 3 deletions(-) diff --git a/packages/trace-viewer/src/ui/actionList.css b/packages/trace-viewer/src/ui/actionList.css index 7161559c62af6..b54ec7fd0d331 100644 --- a/packages/trace-viewer/src/ui/actionList.css +++ b/packages/trace-viewer/src/ui/actionList.css @@ -49,10 +49,20 @@ color: var(--vscode-foreground); } -.action-location > span { +.action-location > button { margin: 0 4px; cursor: pointer; text-decoration: underline; + background: none; + border: none; + padding: 0; + color: inherit; + font: inherit; +} + +.action-location > button:focus-visible { + outline: 1px solid var(--vscode-focusBorder); + outline-offset: -1px; } .action-duration { diff --git a/packages/trace-viewer/src/ui/errorsTab.tsx b/packages/trace-viewer/src/ui/errorsTab.tsx index 36d65c4b7cc97..a10e0af5d9865 100644 --- a/packages/trace-viewer/src/ui/errorsTab.tsx +++ b/packages/trace-viewer/src/ui/errorsTab.tsx @@ -73,7 +73,7 @@ function ErrorView({ message, error, sdkLanguage, revealInSource }: { message: s }}> {error.action && renderAction(error.action, { sdkLanguage })} {location &&
- @ revealInSource(error)}>{location} + @
} diff --git a/packages/trace-viewer/src/ui/networkFilters.tsx b/packages/trace-viewer/src/ui/networkFilters.tsx index dedb250dae895..a08f9a99cf815 100644 --- a/packages/trace-viewer/src/ui/networkFilters.tsx +++ b/packages/trace-viewer/src/ui/networkFilters.tsx @@ -35,6 +35,7 @@ export const NetworkFilters = ({ filterState, onFilterStateChange }: { onFilterStateChange({ ...filterState, searchValue: e.target.value })} diff --git a/packages/trace-viewer/src/ui/uiModeFiltersView.tsx b/packages/trace-viewer/src/ui/uiModeFiltersView.tsx index 0579a741e1d89..722f1e758ba1b 100644 --- a/packages/trace-viewer/src/ui/uiModeFiltersView.tsx +++ b/packages/trace-viewer/src/ui/uiModeFiltersView.tsx @@ -46,7 +46,7 @@ export const FiltersView: React.FC<{ { setFilterText(e.target.value); }} diff --git a/tests/library/trace-viewer.spec.ts b/tests/library/trace-viewer.spec.ts index a88c9cb3b4b89..3c7b63deb76de 100644 --- a/tests/library/trace-viewer.spec.ts +++ b/tests/library/trace-viewer.spec.ts @@ -649,6 +649,8 @@ test('should filter network requests by url', async ({ page, runAndTrace, server await traceViewer.selectAction('Navigate'); await traceViewer.showNetworkTab(); + await expect(traceViewer.page.getByRole('searchbox', { name: 'Filter network' })).toBeVisible(); + await traceViewer.page.getByPlaceholder('Filter network').fill('script.'); await expect(traceViewer.networkRequests).toHaveCount(1); await expect(traceViewer.networkRequests.getByText('script.js')).toBeVisible(); @@ -1362,6 +1364,24 @@ test('should highlight expect failure', async ({ page, server, runAndTrace }) => await expect(traceViewer.errorMessages.nth(0)).toHaveText('Expect failed'); }); +test('should open error source from the keyboard', async ({ page, server, runAndTrace }) => { + test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/42463' }); + const traceViewer = await runAndTrace(async () => { + try { + await page.goto(server.EMPTY_PAGE); + await expect(page).toHaveTitle('foo', { timeout: 100 }); + } catch (e) { + } + }); + + await traceViewer.showErrorsTab(); + const sourceLink = traceViewer.page.getByRole('button', { name: /Go to source:/ }); + await expect(sourceLink).toBeVisible(); + await sourceLink.focus(); + await sourceLink.press('Enter'); + await expect(traceViewer.page.getByRole('tab', { name: 'Source', selected: true })).toBeVisible(); +}); + test('should show action source', async ({ showTraceViewer }) => { const traceViewer = await showTraceViewer(traceFile); await traceViewer.selectAction('Click'); diff --git a/tests/playwright-test/ui-mode-test-filters.spec.ts b/tests/playwright-test/ui-mode-test-filters.spec.ts index f549d150e4b09..3b3992a2f6d3d 100644 --- a/tests/playwright-test/ui-mode-test-filters.spec.ts +++ b/tests/playwright-test/ui-mode-test-filters.spec.ts @@ -91,6 +91,12 @@ test('should toggle filters from the keyboard', async ({ runUITest }) => { await expect(summary).toHaveAttribute('aria-expanded', 'false'); }); +test('should expose an accessible name for the filter input', async ({ runUITest }) => { + test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/42463' }); + const { page } = await runUITest(basicTestTree); + await expect(page.getByRole('searchbox', { name: 'Filter (e.g. text, @tag)' })).toBeVisible(); +}); + test('should filter by status', async ({ runUITest }) => { const { page } = await runUITest(basicTestTree); From f4727a6712275684344044f0ce13030334caf2cb Mon Sep 17 00:00:00 2001 From: scs0209 Date: Mon, 31 Aug 2026 21:25:05 +0900 Subject: [PATCH 2/2] test(trace-viewer): drop redundant a11y regression tests Per review feedback, remove standalone filter-name and keyboard source tests; the network filter assertion in the existing spec is enough. Co-authored-by: Cursor --- tests/library/trace-viewer.spec.ts | 18 ------------------ .../ui-mode-test-filters.spec.ts | 6 ------ 2 files changed, 24 deletions(-) diff --git a/tests/library/trace-viewer.spec.ts b/tests/library/trace-viewer.spec.ts index 3c7b63deb76de..7852c68482f68 100644 --- a/tests/library/trace-viewer.spec.ts +++ b/tests/library/trace-viewer.spec.ts @@ -1364,24 +1364,6 @@ test('should highlight expect failure', async ({ page, server, runAndTrace }) => await expect(traceViewer.errorMessages.nth(0)).toHaveText('Expect failed'); }); -test('should open error source from the keyboard', async ({ page, server, runAndTrace }) => { - test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/42463' }); - const traceViewer = await runAndTrace(async () => { - try { - await page.goto(server.EMPTY_PAGE); - await expect(page).toHaveTitle('foo', { timeout: 100 }); - } catch (e) { - } - }); - - await traceViewer.showErrorsTab(); - const sourceLink = traceViewer.page.getByRole('button', { name: /Go to source:/ }); - await expect(sourceLink).toBeVisible(); - await sourceLink.focus(); - await sourceLink.press('Enter'); - await expect(traceViewer.page.getByRole('tab', { name: 'Source', selected: true })).toBeVisible(); -}); - test('should show action source', async ({ showTraceViewer }) => { const traceViewer = await showTraceViewer(traceFile); await traceViewer.selectAction('Click'); diff --git a/tests/playwright-test/ui-mode-test-filters.spec.ts b/tests/playwright-test/ui-mode-test-filters.spec.ts index 3b3992a2f6d3d..f549d150e4b09 100644 --- a/tests/playwright-test/ui-mode-test-filters.spec.ts +++ b/tests/playwright-test/ui-mode-test-filters.spec.ts @@ -91,12 +91,6 @@ test('should toggle filters from the keyboard', async ({ runUITest }) => { await expect(summary).toHaveAttribute('aria-expanded', 'false'); }); -test('should expose an accessible name for the filter input', async ({ runUITest }) => { - test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/42463' }); - const { page } = await runUITest(basicTestTree); - await expect(page.getByRole('searchbox', { name: 'Filter (e.g. text, @tag)' })).toBeVisible(); -}); - test('should filter by status', async ({ runUITest }) => { const { page } = await runUITest(basicTestTree);