diff --git a/packages/html-reporter/src/headerView.tsx b/packages/html-reporter/src/headerView.tsx
index 01f92f1ecb..9926208711 100644
--- a/packages/html-reporter/src/headerView.tsx
+++ b/packages/html-reporter/src/headerView.tsx
@@ -49,13 +49,20 @@ export const HeaderView: React.FC {
event.preventDefault();
- navigate(`#?q=${filterText ? encodeURIComponent(filterText) : ''}`);
+ if (filterText)
+ navigate(`#?` + new URLSearchParams({ q: filterText }));
+ else
+ navigate('#');
}
}>
{icons.search()}
{/* Use navigationId to reset defaultValue */}
{
- setFilterText(e.target.value);
+ const filterText = e.target.value;
+ if (filterText)
+ navigate(`#?` + new URLSearchParams({ q: filterText }));
+ else
+ navigate('#');
}}>
diff --git a/tests/playwright-test/reporter-html.spec.ts b/tests/playwright-test/reporter-html.spec.ts
index 59d986857f..d6c67d0c6e 100644
--- a/tests/playwright-test/reporter-html.spec.ts
+++ b/tests/playwright-test/reporter-html.spec.ts
@@ -2368,6 +2368,24 @@ for (const useIntermediateMergeReport of [true, false] as const) {
await expect(page.getByText('a.test.js:4', { exact: true })).toBeVisible();
});
+ test('filter should be mirrored in URL', async ({ runInlineTest, showReport, page }) => {
+ const result = await runInlineTest({
+ 'a.test.js': `
+ const { test, expect } = require('@playwright/test');
+ test('test1', async ({}) => { expect(1).toBe(1); });
+ `,
+ }, { reporter: 'dot,html' }, { PLAYWRIGHT_HTML_OPEN: 'never' });
+
+ expect(result.exitCode).toBe(0);
+
+ await showReport();
+ const searchInput = page.locator('.subnav-search-input');
+ await searchInput.fill('a.test.js:3:11');
+ await page.waitForURL(url => new URLSearchParams(url.hash.slice(1)).get('q') === 'a.test.js:3:11');
+ await searchInput.clear();
+ await page.waitForURL(url => !new URLSearchParams(url.hash.slice(1)).has('q'));
+ });
+
test('should properly display beforeEach with and without title', async ({ runInlineTest, showReport, page }) => {
const result = await runInlineTest({
'a.test.js': `