fix(ElementHandle): teach ElementHandle to work with shadowdom (#1227)

Elements in shadow dom erroneously considered that they were detached
from document.

This patch starts using `Element.isConnected` instead of
`document.contains()` call.

Fixes #1061.
This commit is contained in:
Andrey Lushnikov 2017-10-31 12:02:16 -07:00 committed by GitHub
parent 557aa940ec
commit c9a26e11f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 1 deletions

View File

@ -42,7 +42,7 @@ class ElementHandle extends JSHandle {
async _scrollIntoViewIfNeeded() { async _scrollIntoViewIfNeeded() {
const error = await this.executionContext().evaluate(element => { const error = await this.executionContext().evaluate(element => {
if (!element.ownerDocument.contains(element)) if (!element.isConnected)
return 'Node is detached from document'; return 'Node is detached from document';
if (element.nodeType !== Node.ELEMENT_NODE) if (element.nodeType !== Node.ELEMENT_NODE)
return 'Node is not of type HTMLElement'; return 'Node is not of type HTMLElement';

17
test/assets/shadow.html Normal file
View File

@ -0,0 +1,17 @@
<script>
let h1 = null;
let button = null;
let clicked = false;
window.addEventListener('DOMContentLoaded', () => {
const shadowRoot = document.body.attachShadow({mode: 'open'});
h1 = document.createElement('h1');
h1.textContent = 'Hellow Shadow DOM v1';
button = document.createElement('button');
button.textContent = 'Click';
button.addEventListener('click', () => clicked = true);
shadowRoot.appendChild(h1);
shadowRoot.appendChild(button);
});
</script>

View File

@ -1611,6 +1611,12 @@ describe('Page', function() {
await button.click(); await button.click();
expect(await page.evaluate(() => result)).toBe('Clicked'); expect(await page.evaluate(() => result)).toBe('Clicked');
})); }));
it('should work for Shadow DOM v1', SX(async function() {
await page.goto(PREFIX + '/shadow.html');
const buttonHandle = await page.evaluateHandle(() => button);
await buttonHandle.click();
expect(await page.evaluate(() => clicked)).toBe(true);
}));
it('should work for TextNodes', SX(async function() { it('should work for TextNodes', SX(async function() {
await page.goto(PREFIX + '/input/button.html'); await page.goto(PREFIX + '/input/button.html');
const buttonTextNode = await page.evaluateHandle(() => document.querySelector('button').firstChild); const buttonTextNode = await page.evaluateHandle(() => document.querySelector('button').firstChild);