diff --git a/packages/playwright-core/src/server/injected/selectorEvaluator.ts b/packages/playwright-core/src/server/injected/selectorEvaluator.ts index e9a38bb5a6..10f367bf7e 100644 --- a/packages/playwright-core/src/server/injected/selectorEvaluator.ts +++ b/packages/playwright-core/src/server/injected/selectorEvaluator.ts @@ -660,10 +660,28 @@ export function isVisible(element: Element): boolean { const style = element.ownerDocument.defaultView.getComputedStyle(element); if (!style || style.visibility === 'hidden') return false; + if (style.display === 'contents') { + // display:contents is not rendered itself, but its child nodes are. + for (let child = element.firstChild; child; child = child.nextSibling) { + if (child.nodeType === 1 /* Node.ELEMENT_NODE */ && isVisible(child as Element)) + return true; + if (child.nodeType === 3 /* Node.TEXT_NODE */ && isVisibleTextNode(child as Text)) + return true; + } + return false; + } const rect = element.getBoundingClientRect(); return rect.width > 0 && rect.height > 0; } +function isVisibleTextNode(node: Text) { + // https://stackoverflow.com/questions/1461059/is-there-an-equivalent-to-getboundingclientrect-for-text-nodes + const range = document.createRange(); + range.selectNode(node); + const rect = range.getBoundingClientRect(); + return rect.width > 0 && rect.height > 0; +} + function sortInDOMOrder(elements: Element[]): Element[] { type SortEntry = { children: Element[], taken: boolean }; diff --git a/tests/page/selectors-misc.spec.ts b/tests/page/selectors-misc.spec.ts index 7ef29a5bb3..9314922d80 100644 --- a/tests/page/selectors-misc.spec.ts +++ b/tests/page/selectors-misc.spec.ts @@ -306,8 +306,7 @@ it('data-testid on the handle should be relative', async ({ page }) => { expect(await page.$eval(`div >> data-testid=find-me`, e => e.id)).toBe('target2'); }); -it('should consider display:contents elements visible', async ({ page }) => { - it.fixme(true, 'Nested
returns empty client rect'); +it('should properly determine visibility of display:contents elements', async ({ page }) => { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/11202' }); await page.setContent(` @@ -315,4 +314,28 @@ it('should consider display:contents elements visible', async ({ page }) => {
DISPLAY CONTENTS
`); await page.waitForSelector('"DISPLAY CONTENTS"'); + + await page.setContent(` +