fix(click): climb the hit target hierarchy to anchor (#14235)

fix(click): climb the hit target hierarcchy to anchor
This commit is contained in:
Pavel Feldman 2022-05-18 10:01:34 -07:00 committed by GitHub
parent 3c6146c9ec
commit b5beeab98b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 5 deletions

View file

@ -716,15 +716,15 @@ export class InjectedScript {
} }
checkHitTargetAt(node: Node, point: { x: number, y: number }): 'error:notconnected' | 'done' | { hitTargetDescription: string } { checkHitTargetAt(node: Node, point: { x: number, y: number }): 'error:notconnected' | 'done' | { hitTargetDescription: string } {
let element: Element | null | undefined = node.nodeType === Node.ELEMENT_NODE ? (node as Element) : node.parentElement; const element: Element | null | undefined = node.nodeType === Node.ELEMENT_NODE ? (node as Element) : node.parentElement;
if (!element || !element.isConnected) if (!element || !element.isConnected)
return 'error:notconnected'; return 'error:notconnected';
element = element.closest('button, [role=button]') || element;
const hitElement = this.deepElementFromPoint(document, point.x, point.y); const hitElement = this.deepElementFromPoint(document, point.x, point.y);
return this._expectHitTargetParent(hitElement, element); return this._expectHitTargetParent(hitElement, element);
} }
private _expectHitTargetParent(hitElement: Element | undefined, targetElement: Element) { private _expectHitTargetParent(hitElement: Element | undefined, targetElement: Element) {
targetElement = targetElement.closest('button, [role=button], a, [role=link]') || targetElement;
const hitParents: Element[] = []; const hitParents: Element[] = [];
while (hitElement && hitElement !== targetElement) { while (hitElement && hitElement !== targetElement) {
hitParents.push(hitElement); hitParents.push(hitElement);
@ -753,10 +753,9 @@ export class InjectedScript {
} }
setupHitTargetInterceptor(node: Node, action: 'hover' | 'tap' | 'mouse', blockAllEvents: boolean): HitTargetInterceptionResult | 'error:notconnected' { setupHitTargetInterceptor(node: Node, action: 'hover' | 'tap' | 'mouse', blockAllEvents: boolean): HitTargetInterceptionResult | 'error:notconnected' {
const maybeElement: Element | null | undefined = node.nodeType === Node.ELEMENT_NODE ? (node as Element) : node.parentElement; const element: Element | null | undefined = node.nodeType === Node.ELEMENT_NODE ? (node as Element) : node.parentElement;
if (!maybeElement || !maybeElement.isConnected) if (!element || !element.isConnected)
return 'error:notconnected'; return 'error:notconnected';
const element = maybeElement.closest('button, [role=button]') || maybeElement;
const events = { const events = {
'hover': kHoverHitTargetInterceptorEvents, 'hover': kHoverHitTargetInterceptorEvents,

View file

@ -611,6 +611,18 @@ it('should climb up to [role=button]', async ({ page }) => {
expect(await page.evaluate('__CLICKED')).toBe(true); expect(await page.evaluate('__CLICKED')).toBe(true);
}); });
it('should climb up to a anchor', async ({ page }) => {
await page.setContent(`<a href="javascript:window.__CLICKED=true;" id="outer"><div id="inner" style="pointer-events: none">Inner</div></a>`);
await page.click('#inner');
expect(await page.evaluate('__CLICKED')).toBe(true);
});
it('should climb up to a [role=link]', async ({ page }) => {
await page.setContent(`<div role=link onclick="javascript:window.__CLICKED=true;" id="outer"><div id="inner" style="pointer-events: none">Inner</div></div>`);
await page.click('#inner');
expect(await page.evaluate('__CLICKED')).toBe(true);
});
it('should wait for BUTTON to be clickable when it has pointer-events:none', async ({ page }) => { it('should wait for BUTTON to be clickable when it has pointer-events:none', async ({ page }) => {
await page.setContent('<button onclick="javascript:window.__CLICKED=true;" style="pointer-events:none"><span>Click target</span></button>'); await page.setContent('<button onclick="javascript:window.__CLICKED=true;" style="pointer-events:none"><span>Click target</span></button>');
let done = false; let done = false;