From f29f8c34f1ccd885bcf95490bdaa3000a0479b5b Mon Sep 17 00:00:00 2001 From: Thavamani Murugan Date: Sat, 25 Apr 2026 15:20:03 +0530 Subject: [PATCH] fix(test): deduplicate tags when same tag appears in multiple scopes Fixes: https://github.com/microsoft/playwright/issues/40368 --- packages/playwright/src/common/test.ts | 5 +---- tests/playwright-test/test-tag.spec.ts | 28 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/packages/playwright/src/common/test.ts b/packages/playwright/src/common/test.ts index fa8d8c20032d0..7b2ae6aa806e5 100644 --- a/packages/playwright/src/common/test.ts +++ b/packages/playwright/src/common/test.ts @@ -303,10 +303,7 @@ export class TestCase extends Base implements reporterTypes.TestCase { this.parent._collectTagTitlePath(path); path.push(this.title); const titleTags = path.join(' ').match(/@[\S]+/g) || []; - return [ - ...titleTags, - ...this._tags, - ]; + return [...new Set([...titleTags, ...this._tags])]; } _serialize(): any { diff --git a/tests/playwright-test/test-tag.spec.ts b/tests/playwright-test/test-tag.spec.ts index 31cc1371b4bad..9b9f5b6db451b 100644 --- a/tests/playwright-test/test-tag.spec.ts +++ b/tests/playwright-test/test-tag.spec.ts @@ -183,6 +183,34 @@ test('should be included in testInfo if coming from describe or global tag', asy expect(result.exitCode).toBe(0); }); +test('should deduplicate tags when same tag appears in both describe and test', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'a.test.ts': ` + import { test, expect } from '@playwright/test'; + test.describe('suite', { tag: '@foo' }, () => { + test('test', { tag: '@foo' }, async ({}, testInfo) => { + expect(testInfo.tags).toStrictEqual(['@foo']); + }); + }); + `, + }); + expect(result.exitCode).toBe(0); +}); + +test('should deduplicate inline tags when same tag appears in both describe title and test title', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'a.test.ts': ` + import { test, expect } from '@playwright/test'; + test.describe('@foo suite', () => { + test('@foo test', async ({}, testInfo) => { + expect(testInfo.tags).toStrictEqual(['@foo']); + }); + }); + `, + }); + expect(result.exitCode).toBe(0); +}); + test('should not parse file names as tags', async ({ runInlineTest }) => { const result = await runInlineTest({ 'reporter.ts': `