From e6f27841475a5628018723196aa4c3c60be96558 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Thu, 24 Sep 2026 10:52:57 +0100 Subject: [PATCH] chore(server): remove unused noAutoWaiting action option The only real setters of noAutoWaiting were removed together with "perform" in #39626. Since then it was only reachable through the __testHookNoAutoWaiting test hook. --- packages/playwright-core/src/server/dom.ts | 17 +++--------- packages/playwright-core/src/server/frames.ts | 26 ++++++------------ packages/playwright-core/src/server/types.ts | 1 - tests/page/page-click.spec.ts | 27 ------------------- .../expectations/webkit-webview-page.txt | 1 - 5 files changed, 12 insertions(+), 60 deletions(-) diff --git a/packages/playwright-core/src/server/dom.ts b/packages/playwright-core/src/server/dom.ts index 186d95a3d1d03..073531eed4398 100644 --- a/packages/playwright-core/src/server/dom.ts +++ b/packages/playwright-core/src/server/dom.ts @@ -314,11 +314,10 @@ export class ElementHandle extends js.JSHandle { }; } - async _retryAction(progress: Progress, actionName: string, action: (progress: Progress, retry: number) => Promise, options: { trial?: boolean, force?: boolean, skipActionPreChecks?: boolean, noAutoWaiting?: boolean }): Promise<'error:notconnected' | 'done'> { + async _retryAction(progress: Progress, actionName: string, action: (progress: Progress, retry: number) => Promise, options: { trial?: boolean, force?: boolean, skipActionPreChecks?: boolean }): Promise<'error:notconnected' | 'done'> { let retry = 0; // We progressively wait longer between retries, up to 500ms. const waitTime = [0, 20, 100, 100, 500]; - const noAutoWaiting = (options as any).__testHookNoAutoWaiting ?? options.noAutoWaiting; while (true) { if (retry) { @@ -333,43 +332,35 @@ export class ElementHandle extends js.JSHandle { } else { progress.log(`attempting ${actionName} action${options.trial ? ' (trial run)' : ''}`); } - if (!options.skipActionPreChecks && !options.force && !noAutoWaiting) + if (!options.skipActionPreChecks && !options.force) await this._frame._page.performActionPreChecks(progress); const result = await action(progress, retry); ++retry; if (result === 'error:notvisible') { - if (options.force || noAutoWaiting) + if (options.force) throw new NonRecoverableDOMError('Element is not visible'); progress.log(' element is not visible'); continue; } if (result === 'error:notinviewport') { - if (options.force || noAutoWaiting) + if (options.force) throw new NonRecoverableDOMError('Element is outside of the viewport'); progress.log(' element is outside of the viewport'); continue; } if (result === 'error:optionsnotfound') { - if (noAutoWaiting) - throw new NonRecoverableDOMError('Did not find some options'); progress.log(' did not find some options'); continue; } if (result === 'error:optionnotenabled') { - if (noAutoWaiting) - throw new NonRecoverableDOMError('Option being selected is not enabled'); progress.log(' option being selected is not enabled'); continue; } if (typeof result === 'object' && 'hitTargetDescription' in result) { - if (noAutoWaiting) - throw new NonRecoverableDOMError(`${result.hitTargetDescription} intercepts pointer events`); progress.log(` ${result.hitTargetDescription} intercepts pointer events`); continue; } if (typeof result === 'object' && 'missingState' in result) { - if (noAutoWaiting) - throw new NonRecoverableDOMError(`Element is not ${result.missingState}`); progress.log(` element is not ${result.missingState}`); continue; } diff --git a/packages/playwright-core/src/server/frames.ts b/packages/playwright-core/src/server/frames.ts index e8f1383d2bf60..f2cece219771d 100644 --- a/packages/playwright-core/src/server/frames.ts +++ b/packages/playwright-core/src/server/frames.ts @@ -1193,11 +1193,10 @@ export class Frame extends SdkObject { private async _retryWithProgressIfNotConnected( progress: Progress, selector: string, - options: { strict?: boolean, noAutoWaiting?: boolean, force?: boolean, performActionPreChecks?: boolean, waitForFrameVisible?: boolean }, + options: { strict?: boolean, force?: boolean, performActionPreChecks?: boolean, waitForFrameVisible?: boolean }, action: (progress: Progress, handle: dom.ElementHandle, box: types.Rect | undefined, frameVisible: boolean) => Promise): Promise { progress.log(`waiting for ${this._asLocator(selector)}`); - const noAutoWaiting = (options as any).__testHookNoAutoWaiting ?? options.noAutoWaiting; - const performActionPreChecks = (options.performActionPreChecks ?? !options.force) && !noAutoWaiting; + const performActionPreChecks = options.performActionPreChecks ?? !options.force; const waitForFrameVisible = options.waitForFrameVisible && !options.force; return this.retryWithProgressAndBackoff(progress, async (progress, continuePolling) => { if (performActionPreChecks) @@ -1213,24 +1212,17 @@ export class Frame extends SdkObject { const rect = element?.getBoundingClientRect(); return { log, success: !!element, element, box: rect ? { x: rect.x, y: rect.y, width: rect.width, height: rect.height } : undefined }; }, {})); - if (!resolved) { - if (noAutoWaiting) - throw new dom.NonRecoverableDOMError('Element(s) not found'); + if (!resolved) return continuePolling; - } const result = resolved.result; const { log, success, box } = await progress.race(result.evaluate(r => ({ log: r.log, success: r.success, box: r.box }))); if (log) progress.log(log); if (!success) { - if (noAutoWaiting) - throw new dom.NonRecoverableDOMError('Element(s) not found'); result.dispose(); return continuePolling; } if (waitForFrameVisible && !resolved.frameVisible) { - if (noAutoWaiting) - throw new dom.NonRecoverableDOMError('Element is not visible'); progress.log(' element is inside a hidden frame, retrying'); result.dispose(); return continuePolling; @@ -1240,8 +1232,6 @@ export class Frame extends SdkObject { try { const result = await action(progress, element, box, resolved.frameVisible); if (result === 'error:notconnected') { - if (noAutoWaiting) - throw new dom.NonRecoverableDOMError('Element is not attached to the DOM'); progress.log('element was detached from the DOM, retrying'); return continuePolling; } @@ -1301,11 +1291,11 @@ export class Frame extends SdkObject { return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, { ...options, waitForFrameVisible: true }, (progress, handle, box, frameVisible) => handle._fill(progress, value, options, frameVisible, box))); } - async focus(progress: Progress, selector: string, options: types.StrictOptions & { noAutoWaiting?: boolean }) { + async focus(progress: Progress, selector: string, options: types.StrictOptions) { dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (progress, handle) => handle._focus(progress))); } - async blur(progress: Progress, selector: string, options: types.StrictOptions & { noAutoWaiting?: boolean }) { + async blur(progress: Progress, selector: string, options: types.StrictOptions) { dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (progress, handle) => handle._blur(progress))); } @@ -1430,7 +1420,7 @@ export class Frame extends SdkObject { return await this._retryWithProgressIfNotConnected(progress, selector, { ...options, waitForFrameVisible: true }, (progress, handle, box, frameVisible) => handle._selectOption(progress, elements, values, options, frameVisible, box)); } - async setInputFiles(progress: Progress, selector: string, params: Omit & { noAutoWaiting?: boolean }): Promise { + async setInputFiles(progress: Progress, selector: string, params: Omit): Promise { const inputFileItems = await progress.race(prepareFilesForUpload(this, params)); return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, params, (progress, handle, box) => handle._setInputFiles(progress, inputFileItems, box))); } @@ -1445,11 +1435,11 @@ export class Frame extends SdkObject { dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, { ...options, waitForFrameVisible: true }, (progress, handle, box, frameVisible) => handle._drop(progress, inputFileItems, data, options, frameVisible))); } - async type(progress: Progress, selector: string, text: string, options: { delay?: number, noAutoWaiting?: boolean } & types.StrictOptions) { + async type(progress: Progress, selector: string, text: string, options: { delay?: number } & types.StrictOptions) { return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (progress, handle, box) => handle._type(progress, text, options, box))); } - async press(progress: Progress, selector: string, key: string, options: { delay?: number, noWaitAfter?: boolean, noAutoWaiting?: boolean } & types.StrictOptions) { + async press(progress: Progress, selector: string, key: string, options: { delay?: number, noWaitAfter?: boolean } & types.StrictOptions) { return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (progress, handle, box) => handle._press(progress, key, options, box))); } diff --git a/packages/playwright-core/src/server/types.ts b/packages/playwright-core/src/server/types.ts index 52b10d200f5f2..abbd43c1f9a8b 100644 --- a/packages/playwright-core/src/server/types.ts +++ b/packages/playwright-core/src/server/types.ts @@ -37,7 +37,6 @@ export type NavigateOptions = { export type CommonActionOptions = StrictOptions & { force?: boolean, - noAutoWaiting?: boolean, scroll?: 'auto' | 'none', }; diff --git a/tests/page/page-click.spec.ts b/tests/page/page-click.spec.ts index 7b7bef30c686c..cf0ac85c22913 100644 --- a/tests/page/page-click.spec.ts +++ b/tests/page/page-click.spec.ts @@ -1352,33 +1352,6 @@ it('should click with tweened mouse movement', async ({ page, browserName, isAnd ]); }); -it('should not wait with noAutoWaiting', async ({ page }) => { - await page.setContent(``); - const error = await page.locator('#target').click({ __testHookNoAutoWaiting: true } as any).catch(e => e); - expect(error.message).toContain('locator.click: Element(s) not found'); -}); - -it('should not wait with noAutoWaiting 2', async ({ page }) => { - await page.setContent(` - -
- -
- `); - const error = await page.locator('button').click({ __testHookNoAutoWaiting: true } as any).catch(e => e); - expect(error.message).toContain('locator.click:
…
intercepts pointer events'); -}); - -it('should not wait with noAutoWaiting 3', async ({ page }) => { - await page.setContent(``); - const error = await page.locator('button').click({ __testHookNoAutoWaiting: true } as any).catch(e => e); - expect(error.message).toContain('locator.click: Element is not enabled'); -}); - it('should abort via signal', async ({ page }) => { await page.setContent(``); const controller = new AbortController(); diff --git a/tests/webview/expectations/webkit-webview-page.txt b/tests/webview/expectations/webkit-webview-page.txt index 60fd542e30512..3c8c82643b5c0 100644 --- a/tests/webview/expectations/webkit-webview-page.txt +++ b/tests/webview/expectations/webkit-webview-page.txt @@ -363,7 +363,6 @@ page/page-aria-snapshot-ai.spec.ts › should snapshot a locator inside an ifram # Unexpected pass: test.fail(webkit) expects ephemeral CacheStorage, but the iOS # WebView uses the persistent default data store, so the entry survives reload. page/page-cache-storage.spec.ts › CacheStorage entry should survive page.reload() [fail] -page/page-click.spec.ts › should not wait with noAutoWaiting 2 [fail] page/page-emulate-media.spec.ts › should report hover and fine pointer for desktop [fail] # evaluate() function arguments (#41801) work in the main frame, but the # callback bridge is not wired for subframes, so the evaluate never resolves.