From 38f8a8d3d02263862a6e31e17292a2ee39041715 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Mon, 16 Jun 2025 10:04:43 +0200 Subject: [PATCH 1/3] fix(aria): process children of hidden elements --- packages/injected/src/ariaSnapshot.ts | 19 +++++++++++++++---- tests/page/page-aria-snapshot.spec.ts | 14 ++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/packages/injected/src/ariaSnapshot.ts b/packages/injected/src/ariaSnapshot.ts index c1f2ab4bdc411..e50a44ec70d4f 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,11 @@ 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)) { + // skip this element, but still process its children: https://github.com/w3c/aria/issues/1055 + processElement(ariaNode, element, []); return; + } const ariaChildren: Element[] = []; if (element.hasAttribute('aria-owns')) { diff --git a/tests/page/page-aria-snapshot.spec.ts b/tests/page/page-aria-snapshot.spec.ts index ce19ea435106f..92cb8fb69400d 100644 --- a/tests/page/page-aria-snapshot.spec.ts +++ b/tests/page/page-aria-snapshot.spec.ts @@ -658,3 +658,17 @@ it('should not report textarea textContent', async ({ page }) => { - textbox: After `); }); + +it('show visible children of hidden elements', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36296' } }, async ({ page }) => { + await page.setContent(` +
+
+ +
+
+ `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - button "Button" + `); +}); From 9775c4a4425eb060a90cd5a3acb53c1d33b3cddc Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Fri, 20 Jun 2025 10:30:55 +0200 Subject: [PATCH 2/3] add test for aria-hidden hierarchy --- tests/page/page-aria-snapshot.spec.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/page/page-aria-snapshot.spec.ts b/tests/page/page-aria-snapshot.spec.ts index 92cb8fb69400d..5ba7f75041f28 100644 --- a/tests/page/page-aria-snapshot.spec.ts +++ b/tests/page/page-aria-snapshot.spec.ts @@ -659,7 +659,7 @@ it('should not report textarea textContent', async ({ page }) => { `); }); -it('show visible children of hidden elements', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36296' } }, async ({ page }) => { +it('should show visible children of hidden elements', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36296' } }, async ({ page }) => { await page.setContent(`
@@ -672,3 +672,15 @@ it('show visible children of hidden elements', { annotation: { type: 'issue', de - button "Button" `); }); + +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(''); +}); From 77df8a3c7fbead67dd046897b6de9c0cc6bf8b0c Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Tue, 24 Jun 2025 10:43:11 +0200 Subject: [PATCH 3/3] limit to AI snapshot --- packages/injected/src/ariaSnapshot.ts | 5 +++-- tests/page/page-aria-snapshot-ai.spec.ts | 13 +++++++++++++ tests/page/page-aria-snapshot.spec.ts | 6 ++---- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/injected/src/ariaSnapshot.ts b/packages/injected/src/ariaSnapshot.ts index e50a44ec70d4f..c1f4dc436c426 100644 --- a/packages/injected/src/ariaSnapshot.ts +++ b/packages/injected/src/ariaSnapshot.ts @@ -84,8 +84,9 @@ export function generateAriaTree(rootElement: Element, options?: { forAI?: boole const element = node as Element; if (!isVisible(element, options)) { - // skip this element, but still process its children: https://github.com/w3c/aria/issues/1055 - processElement(ariaNode, element, []); + if (options?.forAI) + // skip this element, but still process its children https://github.com/microsoft/playwright/issues/36296 + processElement(ariaNode, element, []); return; } 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 5ba7f75041f28..d1b35a452eae1 100644 --- a/tests/page/page-aria-snapshot.spec.ts +++ b/tests/page/page-aria-snapshot.spec.ts @@ -659,7 +659,7 @@ it('should not report textarea textContent', async ({ page }) => { `); }); -it('should show visible children of hidden elements', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36296' } }, async ({ page }) => { +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(`
@@ -668,9 +668,7 @@ it('should show visible children of hidden elements', { annotation: { type: 'iss
`); - await checkAndMatchSnapshot(page.locator('body'), ` - - button "Button" - `); + 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 }) => {