diff --git a/src/server/dom.ts b/src/server/dom.ts index 2ccb6f71a722b..121b37abe21da 100644 --- a/src/server/dom.ts +++ b/src/server/dom.ts @@ -273,11 +273,22 @@ export class ElementHandle extends js.JSHandle { async _retryPointerAction(progress: Progress, actionName: string, waitForEnabled: boolean, action: (point: types.Point) => Promise, options: types.PointerActionOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions): Promise<'error:notconnected' | 'done'> { - let first = true; + let retry = 0; + // We progressively wait longer between retries, up to 500ms. + const waitTime = [0, 20, 100, 500]; while (progress.isRunning()) { - progress.log(`${first ? 'attempting' : 'retrying'} ${actionName} action`); + if (retry) { + progress.log(`retrying ${actionName} action, attempt #${retry}`); + const timeout = waitTime[Math.min(retry - 1, waitTime.length - 1)]; + if (timeout) { + progress.log(` waiting ${timeout}ms`); + await this._evaluateInUtility(([injected, node, timeout]) => new Promise(f => setTimeout(f, timeout)), timeout); + } + } else { + progress.log(`attempting ${actionName} action`); + } const result = await this._performPointerAction(progress, actionName, waitForEnabled, action, options); - first = false; + ++retry; if (result === 'error:notvisible') { if (options.force) throw new Error('Element is not visible'); diff --git a/test/click-timeout-3.spec.ts b/test/click-timeout-3.spec.ts index d3c571223d3e9..712aefdc4750c 100644 --- a/test/click-timeout-3.spec.ts +++ b/test/click-timeout-3.spec.ts @@ -54,6 +54,7 @@ it('should timeout waiting for hit target', async ({page, server}) => { expect(error.message).toContain('elementHandle.click: Timeout 5000ms exceeded.'); expect(error.message).toContain('
intercepts pointer events'); expect(error.message).toContain('retrying click action'); + expect(error.message).toContain('waiting 500ms'); }); it('should report wrong hit target subtree', async ({page, server}) => {