diff --git a/src/dom.ts b/src/dom.ts index 4ac6361174..951c1e47f4 100644 --- a/src/dom.ts +++ b/src/dom.ts @@ -239,13 +239,18 @@ export class ElementHandle extends js.JSHandle { async _performPointerAction(action: (point: types.Point) => Promise, deadline: number, options: PointerActionOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}): Promise<'done' | 'retry'> { const { force = false, position } = options; - if (!force && !(options as any).__testHookSkipStablePosition) + const skipStableCheck = (options as any).__testHookSkipStablePosition; + if (!force && !skipStableCheck) await this._waitForDisplayedAtStablePosition(deadline); let paused = false; try { await this._page._delegate.setActivityPaused(true); - paused = true; + + if (typeof skipStableCheck === 'function') + await skipStableCheck(); + else if (skipStableCheck) + await skipStableCheck; // Scroll into view and calculate the point again while paused just in case something has moved. this._page._log(inputLog, 'scrolling into view if needed...'); diff --git a/src/webkit/wkPage.ts b/src/webkit/wkPage.ts index 9b361537e9..e8087a4cfd 100644 --- a/src/webkit/wkPage.ts +++ b/src/webkit/wkPage.ts @@ -762,6 +762,7 @@ export class WKPage implements PageDelegate { } async setActivityPaused(paused: boolean): Promise { + // await this._session.send('Page.setJavaScriptPaused', { paused }); } async getContentQuads(handle: dom.ElementHandle): Promise { diff --git a/test/click.spec.js b/test/click.spec.js index 422b1f85ea..e686b2be03 100644 --- a/test/click.spec.js +++ b/test/click.spec.js @@ -628,6 +628,60 @@ describe('Page.click', function() { await page.click('button'); expect(await page.evaluate(() => window.clicked)).toBe(true); }); + it.fail(CHROMIUM || WEBKIT || FFOX)('should pause animations', async({page}) => { + // This test requires pausing the page. + await page.setContent(` +
+ +
+ `); + await page.click('#target', { __testHookSkipStablePosition: new Promise(f => setTimeout(f, 100)) }); + expect(await page.evaluate(() => window.clicked)).toBe(true); + }); + it.fail(CHROMIUM || WEBKIT || FFOX)('should defer timers', async({page}) => { + // This test requires pausing the page. + await page.setContent(``); + await page.click('button', { __testHookSkipStablePosition: async () => { + // Schedule a timer that hides the element + await page.evaluate(() => setTimeout(() => button.style.display = 'none', 0)); + // Allow enough time for timer to fire + await page.waitForTimeout(100); + }}); + expect(await page.evaluate(() => window.clicked)).toBe(true); + }); + it.fail(CHROMIUM || WEBKIT || FFOX)('should defer rafs', async({page}) => { + // This test requires pausing the page. + await page.setContent(``); + await page.click('button', { __testHookSkipStablePosition: async () => { + // Schedule a timer that hides the element + await page.evaluate(() => requestAnimationFrame(() => button.style.display = 'none')); + // Allow enough time for raf to fire + await page.waitForTimeout(100); + }}); + expect(await page.evaluate(() => window.clicked)).toBe(true); + }); + it.fail(CHROMIUM || WEBKIT || FFOX)('should defer fetch', async({page, server}) => { + // This test requires pausing the page. + await page.goto(server.EMPTY_PAGE); + await page.setContent(``); + await page.click('button', { __testHookSkipStablePosition: async () => { + // Fetch that would immediately delete button. + page.evaluate(() => fetch(window.location.href).then(() => button.style.display = 'none')); + // Allow enough time for raf to fire + await page.waitForTimeout(100); + }}); + expect(await page.evaluate(() => window.clicked)).toBe(true); + }); }); describe('Page.check', function() {