Skip to content

Commit effeaaf

Browse files
authored
fix(click): force any hover effects before waiting for hit target (#1869)
This way, any on-hover animations or click blockers will be accounted for.
1 parent 6231d50 commit effeaaf

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

src/dom.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
226226
const point = position ? await this._offsetPoint(position) : await this._clickablePoint();
227227
point.x = (point.x * 100 | 0) / 100;
228228
point.y = (point.y * 100 | 0) / 100;
229+
await this._page.mouse.move(point.x, point.y); // Force any hover effects before waiting for hit target.
229230
if (!force)
230231
await this._waitForHitTargetAt(point, deadline);
231232

test/click.spec.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ describe('Page.click', function() {
198198
'mouseover',
199199
'mouseenter',
200200
'mousemove',
201+
'mousemove',
201202
'mousedown',
202203
'mouseup',
203204
'click',
@@ -596,6 +597,36 @@ describe('Page.click', function() {
596597
expect(clicked).toBe(true);
597598
expect(await page.evaluate(() => window.clicked)).toBe(true);
598599
});
600+
it('should fail when element is blocked on hover', async({page, server}) => {
601+
await page.setContent(`<style>
602+
container { display: block; position: relative; width: 200px; height: 50px; }
603+
div, button { position: absolute; left: 0; top: 0; bottom: 0; right: 0; }
604+
div { pointer-events: none; }
605+
container:hover div { pointer-events: auto; background: red; }
606+
</style>
607+
<container>
608+
<button onclick="window.clicked=true">Click me</button>
609+
<div></div>
610+
</container>`);
611+
const error = await page.click('button', { timeout: 3000 }).catch(e => e);
612+
expect(error.message).toBe('waiting for element to receive pointer events failed: timeout exceeded');
613+
expect(await page.evaluate(() => window.clicked)).toBe(undefined);
614+
});
615+
it('should wait while element is blocked on hover', async({page, server}) => {
616+
await page.setContent(`<style>
617+
@keyframes move-out { from { marign-left: 0; } to { margin-left: 150px; } }
618+
container { display: block; position: relative; width: 200px; height: 50px; }
619+
div, button { position: absolute; left: 0; top: 0; bottom: 0; right: 0; }
620+
div { pointer-events: none; }
621+
container:hover div { pointer-events: auto; background: red; animation: 3s linear move-out; animation-fill-mode: forwards; }
622+
</style>
623+
<container>
624+
<button onclick="window.clicked=true">Click me</button>
625+
<div></div>
626+
</container>`);
627+
await page.click('button');
628+
expect(await page.evaluate(() => window.clicked)).toBe(true);
629+
});
599630
});
600631

601632
describe('Page.check', function() {

0 commit comments

Comments
 (0)