diff --git a/packages/playwright-core/src/server/injected/injectedScript.ts b/packages/playwright-core/src/server/injected/injectedScript.ts index 0571ef9ced..0cd494830b 100644 --- a/packages/playwright-core/src/server/injected/injectedScript.ts +++ b/packages/playwright-core/src/server/injected/injectedScript.ts @@ -840,6 +840,15 @@ export class InjectedScript { elements.unshift(singleElement); } } + if (elements[0] && elements[0].shadowRoot === root && elements[1] === singleElement) { + // Workaround webkit but where first two elements are swapped: + // + // #shadow root + // + // elementsFromPoint produces [, ], while it should be [, ] + // In this case, just ignore . + elements.shift(); + } const innerElement = elements[0] as Element | undefined; if (!innerElement) break; diff --git a/tests/library/hit-target.spec.ts b/tests/library/hit-target.spec.ts index 9e5362ab18..4b97ffd6dd 100644 --- a/tests/library/hit-target.spec.ts +++ b/tests/library/hit-target.spec.ts @@ -442,3 +442,25 @@ it('should click in iframe with padding 2', async ({ page }) => { await locator.click(); expect(await page.evaluate('window._clicked')).toBe(true); }); + +it('should click in custom element', async ({ page }) => { + await page.setContent(` + + + + + + + `); + await page.locator('input').click(); + expect(await page.evaluate('window.__clicked')).toBe(true); +});