diff --git a/browsers.json b/browsers.json index a3d003911e..4db8277391 100644 --- a/browsers.json +++ b/browsers.json @@ -6,7 +6,7 @@ }, { "name": "firefox", - "revision": "1108" + "revision": "1111" }, { "name": "webkit", diff --git a/src/dom.ts b/src/dom.ts index bc8ceffe06..3516ff25b7 100644 --- a/src/dom.ts +++ b/src/dom.ts @@ -213,7 +213,10 @@ export class ElementHandle extends js.JSHandle { } async scrollIntoViewIfNeeded() { - throwIfNotConnected(await this._scrollRectIntoViewIfNeeded()); + const result = await this._scrollRectIntoViewIfNeeded(); + if (result === 'notvisible') + throw new Error('Element is not visible'); + throwIfNotConnected(result); } private async _clickablePoint(): Promise { diff --git a/src/firefox/ffPage.ts b/src/firefox/ffPage.ts index 882a12d43f..92923a7920 100644 --- a/src/firefox/ffPage.ts +++ b/src/firefox/ffPage.ts @@ -418,6 +418,8 @@ export class FFPage implements PageDelegate { }).then(() => 'done' as const).catch(e => { if (e instanceof Error && e.message.includes('Node is detached from document')) return 'notconnected'; + if (e instanceof Error && e.message.includes('Node does not have a layout object')) + return 'notvisible'; throw e; }); } diff --git a/test/elementhandle.spec.js b/test/elementhandle.spec.js index 2598a3e3ab..4f53b24a04 100644 --- a/test/elementhandle.spec.js +++ b/test/elementhandle.spec.js @@ -323,6 +323,41 @@ describe('ElementHandle.scrollIntoViewIfNeeded', function() { await page.evaluate(() => window.scrollTo(0, 0)); } }); + it('should throw for detached element', async({page, server}) => { + await page.setContent('
Hello
'); + const div = await page.$('div'); + await div.evaluate(div => div.remove()); + const error = await div.scrollIntoViewIfNeeded().catch(e => e); + expect(error.message).toContain('Element is not attached to the DOM'); + }); + it('should throw for display:none element', async({page, server}) => { + await page.setContent('
Hello
'); + const div = await page.$('div'); + const error = await div.scrollIntoViewIfNeeded().catch(e => e); + expect(error.message).toContain('Element is not visible'); + }); + it('should throw for nested display:none element', async({page, server}) => { + await page.setContent('
Hello
'); + const div = await page.$('div'); + const error = await div.scrollIntoViewIfNeeded().catch(e => e); + expect(error.message).toContain('Element is not visible'); + }); + it('should throw for display:contents element', async({page, server}) => { + await page.setContent('
Hello
'); + const div = await page.$('div'); + const error = await div.scrollIntoViewIfNeeded().catch(e => e); + expect(error.message).toContain('Element is not visible'); + }); + it('should scroll a zero-sized element', async({page, server}) => { + await page.setContent('
'); + const br = await page.$('br'); + await br.scrollIntoViewIfNeeded(); + }); + it('should scroll a visibility:hidden element', async({page, server}) => { + await page.setContent('
Hello
'); + const div = await page.$('div'); + await div.scrollIntoViewIfNeeded(); + }); }); describe('ElementHandle.fill', function() {