chore: move retargeting from expectHitTarget to retarget (#16474)

This aligns all retargeting in a single place, so that we
can pass around "retarget strategy" to make sure we retarget
as expected in every single action.
This commit is contained in:
Dmitry Gozman 2022-08-11 13:06:12 -07:00 committed by GitHub
parent acc9b528ea
commit 51076d55ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -437,14 +437,18 @@ export class InjectedScript {
return { left: parseInt(style.borderLeftWidth || '', 10), top: parseInt(style.borderTopWidth || '', 10) }; return { left: parseInt(style.borderLeftWidth || '', 10), top: parseInt(style.borderTopWidth || '', 10) };
} }
retarget(node: Node, behavior: 'none' | 'follow-label' | 'no-follow-label'): Element | null { retarget(node: Node, behavior: 'none' | 'follow-label' | 'no-follow-label' | 'button-link'): Element | null {
let element = node.nodeType === Node.ELEMENT_NODE ? node as Element : node.parentElement; let element = node.nodeType === Node.ELEMENT_NODE ? node as Element : node.parentElement;
if (!element) if (!element)
return null; return null;
if (behavior === 'none') if (behavior === 'none')
return element; return element;
if (!element.matches('input, textarea, select')) if (!element.matches('input, textarea, select')) {
element = element.closest('button, [role=button], [role=checkbox], [role=radio]') || element; if (behavior === 'button-link')
element = element.closest('button, [role=button], a, [role=link]') || element;
else
element = element.closest('button, [role=button], [role=checkbox], [role=radio]') || element;
}
if (behavior === 'follow-label') { if (behavior === 'follow-label') {
if (!element.matches('input, textarea, button, select, [role=button], [role=checkbox], [role=radio]') && if (!element.matches('input, textarea, button, select, [role=button], [role=checkbox], [role=radio]') &&
!(element as any).isContentEditable) { !(element as any).isContentEditable) {
@ -723,7 +727,6 @@ export class InjectedScript {
} }
expectHitTargetParent(hitElement: Element | undefined, targetElement: Element) { 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);
@ -782,7 +785,7 @@ export class InjectedScript {
// 2l. All navigations triggered between 2g-2k are awaited to be either committed or canceled. // 2l. All navigations triggered between 2g-2k are awaited to be either committed or canceled.
// 2m. If failed, wait for increasing amount of time before the next retry. // 2m. If failed, wait for increasing amount of time before the next retry.
setupHitTargetInterceptor(node: Node, action: 'hover' | 'tap' | 'mouse' | 'drag', hitPoint: { x: number, y: number }, blockAllEvents: boolean): HitTargetInterceptionResult | 'error:notconnected' | string /* hitTargetDescription */ { setupHitTargetInterceptor(node: Node, action: 'hover' | 'tap' | 'mouse' | 'drag', hitPoint: { x: number, y: number }, blockAllEvents: boolean): HitTargetInterceptionResult | 'error:notconnected' | string /* hitTargetDescription */ {
const element: Element | null | undefined = node.nodeType === Node.ELEMENT_NODE ? (node as Element) : node.parentElement; const element = this.retarget(node, 'button-link');
if (!element || !element.isConnected) if (!element || !element.isConnected)
return 'error:notconnected'; return 'error:notconnected';