fix(hit target): account for iframes with padding (#19732)
Padding on iframes moves the `documentElement` inside the iframe, so we should account for it when converting coordinates between frames. Fixes #19613.
This commit is contained in:
parent
3334d89ad7
commit
0b223b9036
|
|
@ -877,7 +877,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
|
|||
return { framePoint: undefined };
|
||||
}
|
||||
// Translate from viewport coordinates to frame coordinates.
|
||||
const pointInFrame = { x: point.x - box.x - style.borderLeft, y: point.y - box.y - style.borderTop };
|
||||
const pointInFrame = { x: point.x - box.x - style.left, y: point.y - box.y - style.top };
|
||||
data.push({ frame, frameElement, pointInFrame });
|
||||
frame = frame.parentFrame()!;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -486,7 +486,7 @@ export class InjectedScript {
|
|||
return { left: parseInt(style.borderLeftWidth || '', 10), top: parseInt(style.borderTopWidth || '', 10) };
|
||||
}
|
||||
|
||||
describeIFrameStyle(iframe: Element): 'error:notconnected' | 'transformed' | { borderLeft: number, borderTop: number } {
|
||||
describeIFrameStyle(iframe: Element): 'error:notconnected' | 'transformed' | { left: number, top: number } {
|
||||
if (!iframe.ownerDocument || !iframe.ownerDocument.defaultView)
|
||||
return 'error:notconnected';
|
||||
const defaultView = iframe.ownerDocument.defaultView;
|
||||
|
|
@ -495,7 +495,10 @@ export class InjectedScript {
|
|||
return 'transformed';
|
||||
}
|
||||
const iframeStyle = defaultView.getComputedStyle(iframe);
|
||||
return { borderLeft: parseInt(iframeStyle.borderLeftWidth || '', 10), borderTop: parseInt(iframeStyle.borderTopWidth || '', 10) };
|
||||
return {
|
||||
left: parseInt(iframeStyle.borderLeftWidth || '', 10) + parseInt(iframeStyle.paddingLeft || '', 10),
|
||||
top: parseInt(iframeStyle.borderTopWidth || '', 10) + parseInt(iframeStyle.paddingTop || '', 10),
|
||||
};
|
||||
}
|
||||
|
||||
retarget(node: Node, behavior: 'none' | 'follow-label' | 'no-follow-label' | 'button-link'): Element | null {
|
||||
|
|
|
|||
|
|
@ -394,3 +394,51 @@ it('should detect overlayed element in a transformed iframe', async ({ page }) =
|
|||
const error = await locator.click({ timeout: 2000 }).catch(e => e);
|
||||
expect(error.message).toContain('<section>Overlay</section> intercepts pointer events');
|
||||
});
|
||||
|
||||
it('should click in iframe with padding', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<style>
|
||||
body, html, iframe { margin: 0; padding: 0; border: none; box-sizing: border-box; }
|
||||
iframe { background: gray; width: 200px; height: 200px; padding-top: 100px; }
|
||||
</style>
|
||||
<iframe srcdoc="
|
||||
<style>
|
||||
body, html { margin: 0; padding: 0; }
|
||||
div { height: 100px; }
|
||||
</style>
|
||||
<div>Non-target</div>
|
||||
<div id=target>Target</div>
|
||||
<div>Non-target</div>
|
||||
<script>
|
||||
document.querySelector('#target').addEventListener('click', () => window.top._clicked = true);
|
||||
</script>
|
||||
"></iframe>
|
||||
`);
|
||||
const locator = page.frameLocator('iframe').locator('#target');
|
||||
await locator.click();
|
||||
expect(await page.evaluate('window._clicked')).toBe(true);
|
||||
});
|
||||
|
||||
it('should click in iframe with padding 2', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<style>
|
||||
body, html, iframe { margin: 0; padding: 0; border: none; box-sizing: content-box; }
|
||||
iframe { background: gray; width: 200px; height: 200px; padding-top: 100px; }
|
||||
</style>
|
||||
<iframe srcdoc="
|
||||
<style>
|
||||
body, html { margin: 0; padding: 0; }
|
||||
div { height: 100px; }
|
||||
</style>
|
||||
<div>Non-target</div>
|
||||
<div id=target>Target</div>
|
||||
<div>Non-target</div>
|
||||
<script>
|
||||
document.querySelector('#target').addEventListener('click', () => window.top._clicked = true);
|
||||
</script>
|
||||
"></iframe>
|
||||
`);
|
||||
const locator = page.frameLocator('iframe').locator('#target');
|
||||
await locator.click();
|
||||
expect(await page.evaluate('window._clicked')).toBe(true);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue