diff --git a/packages/playwright-core/src/server/injected/roleUtils.ts b/packages/playwright-core/src/server/injected/roleUtils.ts index 99f3cafa29..498fc189aa 100644 --- a/packages/playwright-core/src/server/injected/roleUtils.ts +++ b/packages/playwright-core/src/server/injected/roleUtils.ts @@ -375,7 +375,8 @@ function getPseudoContent(element: Element, pseudo: '::before' | '::after') { } function getPseudoContentImpl(pseudoStyle: CSSStyleDeclaration | undefined) { - if (!pseudoStyle) + // Note: all browsers ignore display:none and visibility:hidden pseudos. + if (!pseudoStyle || pseudoStyle.display === 'none' || pseudoStyle.visibility === 'hidden') return ''; const content = pseudoStyle.content; if ((content[0] === '\'' && content[content.length - 1] === '\'') || diff --git a/tests/library/role-utils.spec.ts b/tests/library/role-utils.spec.ts index 067053ba11..6c45686f68 100644 --- a/tests/library/role-utils.spec.ts +++ b/tests/library/role-utils.spec.ts @@ -475,6 +475,26 @@ test('should ignore stylesheet from hidden aria-labelledby subtree', async ({ pa expect.soft(await getNameAndRole(page, 'input')).toEqual({ role: 'textbox', name: 'hello' }); }); +test('should not include hidden pseudo into accessible name', async ({ page }) => { + await page.setContent(` + + + hello +
hello
+
+ `); + expect.soft(await getNameAndRole(page, 'a')).toEqual({ role: 'link', name: 'hello hello' }); +}); + function toArray(x: any): any[] { return Array.isArray(x) ? x : [x]; }