diff --git a/packages/injected/src/ariaSnapshot.ts b/packages/injected/src/ariaSnapshot.ts index c1f2ab4bdc411..c1f4dc436c426 100644 --- a/packages/injected/src/ariaSnapshot.ts +++ b/packages/injected/src/ariaSnapshot.ts @@ -47,6 +47,14 @@ type AriaRef = { let lastRef = 0; +function isVisible(element: Element, options?: { forAI?: boolean }): boolean { + if (!roleUtils.isElementHiddenForAria(element)) + return true; + if (options?.forAI && isElementVisible(element)) + return true; + return false; +} + export function generateAriaTree(rootElement: Element, options?: { forAI?: boolean, refPrefix?: string }): AriaSnapshot { const visited = new Set(); @@ -61,6 +69,9 @@ export function generateAriaTree(rootElement: Element, options?: { forAI?: boole visited.add(node); if (node.nodeType === Node.TEXT_NODE && node.nodeValue) { + if (node.parentElement && !isVisible(node.parentElement, options)) + return; + const text = node.nodeValue; // should not report AAA as a child of the textarea. if (ariaNode.role !== 'textbox' && text) @@ -72,11 +83,12 @@ export function generateAriaTree(rootElement: Element, options?: { forAI?: boole return; const element = node as Element; - let isVisible = !roleUtils.isElementHiddenForAria(element); - if (options?.forAI) - isVisible = isVisible || isElementVisible(element); - if (!isVisible) + if (!isVisible(element, options)) { + if (options?.forAI) + // skip this element, but still process its children https://github.com/microsoft/playwright/issues/36296 + processElement(ariaNode, element, []); return; + } const ariaChildren: Element[] = []; if (element.hasAttribute('aria-owns')) { diff --git a/tests/page/page-aria-snapshot-ai.spec.ts b/tests/page/page-aria-snapshot-ai.spec.ts index 35d591bf9fc8e..9fd5ac603eb69 100644 --- a/tests/page/page-aria-snapshot-ai.spec.ts +++ b/tests/page/page-aria-snapshot-ai.spec.ts @@ -252,3 +252,16 @@ it('should auto-wait for blocking CSS', async ({ page, server }) => { `, { waitUntil: 'commit' }); expect(await snapshotForAI(page)).toContainYaml('Hello World'); }); + +it('should show visible children of hidden elements', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36296' } }, async ({ page }) => { + await page.setContent(` +
+
+ +
+ +
+ `); + + expect(await snapshotForAI(page)).toEqual(`- button "Foo" [ref=e3]`); +}); diff --git a/tests/page/page-aria-snapshot.spec.ts b/tests/page/page-aria-snapshot.spec.ts index ce19ea435106f..d1b35a452eae1 100644 --- a/tests/page/page-aria-snapshot.spec.ts +++ b/tests/page/page-aria-snapshot.spec.ts @@ -658,3 +658,27 @@ it('should not report textarea textContent', async ({ page }) => { - textbox: After `); }); + +it('should not show visible children of hidden elements', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36296' } }, async ({ page }) => { + await page.setContent(` +
+
+ +
+
+ `); + + expect(await page.locator('body').ariaSnapshot()).toBe(''); +}); + +it('should not show unhidden children of aria-hidden elements', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36296' } }, async ({ page }) => { + await page.setContent(` + + `); + + expect(await page.locator('body').ariaSnapshot()).toBe(''); +});