fix(click): explicitly fail when element detached during click (#1835)
We used to timeout instead.
This commit is contained in:
parent
629b77271c
commit
af2340c35e
|
|
@ -286,12 +286,16 @@ class Injected {
|
||||||
// and only force layout during actual rafs as a small optimisation.
|
// and only force layout during actual rafs as a small optimisation.
|
||||||
if (++counter === 1)
|
if (++counter === 1)
|
||||||
return false;
|
return false;
|
||||||
|
if (!node.isConnected)
|
||||||
|
return 'Element is not attached to the DOM';
|
||||||
const clientRect = element.getBoundingClientRect();
|
const clientRect = element.getBoundingClientRect();
|
||||||
const rect = { x: clientRect.top, y: clientRect.left, width: clientRect.width, height: clientRect.height };
|
const rect = { x: clientRect.top, y: clientRect.left, width: clientRect.width, height: clientRect.height };
|
||||||
const isDisplayedAndStable = lastRect && rect.x === lastRect.x && rect.y === lastRect.y && rect.width === lastRect.width && rect.height === lastRect.height && rect.width > 0 && rect.height > 0;
|
const isDisplayedAndStable = lastRect && rect.x === lastRect.x && rect.y === lastRect.y && rect.width === lastRect.width && rect.height === lastRect.height && rect.width > 0 && rect.height > 0;
|
||||||
lastRect = rect;
|
lastRect = rect;
|
||||||
return isDisplayedAndStable;
|
return isDisplayedAndStable;
|
||||||
});
|
});
|
||||||
|
if (typeof result === 'string')
|
||||||
|
throw new Error(result);
|
||||||
if (!result)
|
if (!result)
|
||||||
throw new Error(`waiting for element to be displayed and not moving failed: timeout exceeded`);
|
throw new Error(`waiting for element to be displayed and not moving failed: timeout exceeded`);
|
||||||
}
|
}
|
||||||
|
|
@ -303,11 +307,15 @@ class Injected {
|
||||||
if (!element)
|
if (!element)
|
||||||
throw new Error('Element is not attached to the DOM');
|
throw new Error('Element is not attached to the DOM');
|
||||||
const result = await this.poll('raf', timeout, () => {
|
const result = await this.poll('raf', timeout, () => {
|
||||||
|
if (!element!.isConnected)
|
||||||
|
return 'Element is not attached to the DOM';
|
||||||
let hitElement = this._deepElementFromPoint(document, point.x, point.y);
|
let hitElement = this._deepElementFromPoint(document, point.x, point.y);
|
||||||
while (hitElement && hitElement !== element)
|
while (hitElement && hitElement !== element)
|
||||||
hitElement = this._parentElementOrShadowHost(hitElement);
|
hitElement = this._parentElementOrShadowHost(hitElement);
|
||||||
return hitElement === element;
|
return hitElement === element;
|
||||||
});
|
});
|
||||||
|
if (typeof result === 'string')
|
||||||
|
throw new Error(result);
|
||||||
if (!result)
|
if (!result)
|
||||||
throw new Error(`waiting for element to receive mouse events failed: timeout exceeded`);
|
throw new Error(`waiting for element to receive mouse events failed: timeout exceeded`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -554,6 +554,25 @@ describe('Page.click', function() {
|
||||||
if (error2)
|
if (error2)
|
||||||
expect(error2.message).toContain('timeout exceeded');
|
expect(error2.message).toContain('timeout exceeded');
|
||||||
});
|
});
|
||||||
|
it('should fail when element detaches after animation', async({page, server}) => {
|
||||||
|
await page.setContent(`<style>body, html { margin: 0; padding: 0; }</style><button onclick="window.clicked=true">Click me</button>`);
|
||||||
|
await page.$eval('button', button => {
|
||||||
|
button.style.transition = 'margin-left 100000ms linear';
|
||||||
|
});
|
||||||
|
await page.$eval('button', button => {
|
||||||
|
button.style.marginLeft = '100000px';
|
||||||
|
});
|
||||||
|
const handle = await page.$('button');
|
||||||
|
const promise = handle.click().catch(e => e);
|
||||||
|
await page.$eval('button', button => {
|
||||||
|
button.style.marginLeft = button.getBoundingClientRect().left + 'px';
|
||||||
|
button.style.transition = '';
|
||||||
|
button.remove();
|
||||||
|
});
|
||||||
|
const error = await promise;
|
||||||
|
expect(await page.evaluate(() => window.clicked)).toBe(undefined);
|
||||||
|
expect(error.message).toContain('Element is not attached to the DOM');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Page.check', function() {
|
describe('Page.check', function() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue