From 1869bd28d6d4936c2ba1e74e454dfe18e1c825f6 Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Fri, 24 Mar 2023 17:15:44 -0700 Subject: [PATCH] cherry-pick(#21967): chore: allow sibling describes with the same name Fixes https://github.com/microsoft/playwright/issues/21953 --- .../src/isomorphic/teleReceiver.ts | 36 +++++---- packages/trace-viewer/src/ui/watchMode.tsx | 2 +- .../playwright-test/ui-mode-test-tree.spec.ts | 80 +++++++++++++++++++ 3 files changed, 103 insertions(+), 15 deletions(-) diff --git a/packages/playwright-test/src/isomorphic/teleReceiver.ts b/packages/playwright-test/src/isomorphic/teleReceiver.ts index 67a62bfd51faa..af34c45e2e608 100644 --- a/packages/playwright-test/src/isomorphic/teleReceiver.ts +++ b/packages/playwright-test/src/isomorphic/teleReceiver.ts @@ -149,7 +149,6 @@ export class TeleReporterReceiver { } private _onBegin(config: JsonConfig, projects: JsonProject[]) { - const removeMissing = config.listOnly; for (const project of projects) { let projectSuite = this._rootSuite.suites.find(suite => suite.project()!.id === project.id); if (!projectSuite) { @@ -159,7 +158,24 @@ export class TeleReporterReceiver { } const p = this._parseProject(project); projectSuite.project = () => p; - this._mergeSuitesInto(project.suites, projectSuite, removeMissing); + this._mergeSuitesInto(project.suites, projectSuite); + + // Remove deleted tests when listing. Empty suites will be auto-filtered + // in the UI layer. + if (config.listOnly) { + const testIds = new Set(); + const collectIds = (suite: JsonSuite) => { + suite.tests.map(t => t.testId).forEach(testId => testIds.add(testId)); + suite.suites.forEach(collectIds); + }; + project.suites.forEach(collectIds); + + const filterTests = (suite: TeleSuite) => { + suite.tests = suite.tests.filter(t => testIds.has(t.id)); + suite.suites.forEach(filterTests); + }; + filterTests(projectSuite); + } } this._reporter.onBegin?.(this._parseConfig(config), this._rootSuite); } @@ -262,7 +278,7 @@ export class TeleReporterReceiver { }; } - private _mergeSuitesInto(jsonSuites: JsonSuite[], parent: TeleSuite, removeMissing: boolean) { + private _mergeSuitesInto(jsonSuites: JsonSuite[], parent: TeleSuite) { for (const jsonSuite of jsonSuites) { let targetSuite = parent.suites.find(s => s.title === jsonSuite.title); if (!targetSuite) { @@ -273,16 +289,12 @@ export class TeleReporterReceiver { targetSuite.location = jsonSuite.location; targetSuite._fileId = jsonSuite.fileId; targetSuite._parallelMode = jsonSuite.parallelMode; - this._mergeSuitesInto(jsonSuite.suites, targetSuite, removeMissing); - this._mergeTestsInto(jsonSuite.tests, targetSuite, removeMissing); - } - if (removeMissing) { - const suiteMap = new Map(parent.suites.map(p => [p.title, p])); - parent.suites = jsonSuites.map(s => suiteMap.get(s.title)).filter(Boolean) as TeleSuite[]; + this._mergeSuitesInto(jsonSuite.suites, targetSuite); + this._mergeTestsInto(jsonSuite.tests, targetSuite); } } - private _mergeTestsInto(jsonTests: JsonTestCase[], parent: TeleSuite, removeMissing: boolean) { + private _mergeTestsInto(jsonTests: JsonTestCase[], parent: TeleSuite) { for (const jsonTest of jsonTests) { let targetTest = parent.tests.find(s => s.title === jsonTest.title); if (!targetTest) { @@ -293,10 +305,6 @@ export class TeleReporterReceiver { } this._updateTest(jsonTest, targetTest); } - if (removeMissing) { - const testMap = new Map(parent.tests.map(p => [p.title, p])); - parent.tests = jsonTests.map(s => testMap.get(s.title)).filter(Boolean) as TeleTestCase[]; - } } private _updateTest(payload: JsonTestCase, test: TeleTestCase): TeleTestCase { diff --git a/packages/trace-viewer/src/ui/watchMode.tsx b/packages/trace-viewer/src/ui/watchMode.tsx index f9ecb4cd99b97..e7b84fa040e57 100644 --- a/packages/trace-viewer/src/ui/watchMode.tsx +++ b/packages/trace-viewer/src/ui/watchMode.tsx @@ -735,7 +735,7 @@ function createTree(rootSuite: Suite | undefined, projectFilters: Map { for (const suite of parentSuite.suites) { - const title = suite.title; + const title = suite.title || ''; let group = parentGroup.children.find(item => item.title === title) as GroupItem | undefined; if (!group) { group = { diff --git a/tests/playwright-test/ui-mode-test-tree.spec.ts b/tests/playwright-test/ui-mode-test-tree.spec.ts index 9dcfef62ef224..6189190dc8451 100644 --- a/tests/playwright-test/ui-mode-test-tree.spec.ts +++ b/tests/playwright-test/ui-mode-test-tree.spec.ts @@ -142,3 +142,83 @@ test('should merge folder trees', async ({ runUITest }) => { ◯ passes `); }); + +test('should list parametrized tests', async ({ runUITest }) => { + const page = await runUITest({ + 'a.test.ts': ` + import { test } from '@playwright/test'; + test.describe('cookies', () => { + for (const country of ['FR', 'DE', 'LT']) { + test.describe(() => { + test('test ' + country, async ({}) => {}); + }); + } + }) + ` + }); + + await page.getByText('cookies').click(); + await page.keyboard.press('ArrowRight'); + await page.getByText('').click(); + await page.keyboard.press('ArrowRight'); + + await expect.poll(dumpTestTree(page), { timeout: 15000 }).toBe(` + ▼ ◯ a.test.ts + ▼ ◯ cookies + ▼ ◯ <= + ◯ test FR + ◯ test DE + ◯ test LT + `); +}); + +test('should update parametrized tests', async ({ runUITest, writeFiles }) => { + const page = await runUITest({ + 'a.test.ts': ` + import { test } from '@playwright/test'; + test.describe('cookies', () => { + for (const country of ['FR', 'DE', 'LT']) { + test.describe(() => { + test('test ' + country, async ({}) => {}); + }); + } + }) + ` + }); + + await page.getByText('cookies').click(); + await page.keyboard.press('ArrowRight'); + await page.getByText('').click(); + await page.keyboard.press('ArrowRight'); + + await expect.poll(dumpTestTree(page), { timeout: 15000 }).toBe(` + ▼ ◯ a.test.ts + ▼ ◯ cookies + ▼ ◯ <= + ◯ test FR + ◯ test DE + ◯ test LT + `); + + writeFiles({ + 'a.test.ts': ` + import { test } from '@playwright/test'; + test.describe('cookies', () => { + for (const country of ['FR', 'LT']) { + test.describe(() => { + test('test ' + country, async ({}) => {}); + }); + } + }) + ` + }); + + + await expect.poll(dumpTestTree(page), { timeout: 15000 }).toBe(` + ▼ ◯ a.test.ts + ▼ ◯ cookies + ▼ ◯ <= + ◯ test FR + ◯ test LT + `); +}); \ No newline at end of file