2017-01-20 6 views
3

У меня возникают проблемы с использованием Selenium с элементами, находящимися внутри тени DOM. Есть ли уловка? Я делаю что-то неправильно?Использование Selenium для тестирования полимерных элементов и теневых DOM

Вот мой выбор попыток:

var webdriver = require('selenium-webdriver'); 
var driver = new webdriver.Builder().forBrowser('chrome').build(); 

driver.get('https://shop.polymer-project.org/'); 

// Goal is to find shop-app #shadow-root app-header 
// 

// This is OK; no shadow DOMs 
driver.findElement(webdriver.By.css('shop-app')); 

// This fails because: 
// NoSuchElementError: no such element: Unable to locate element 
driver.findElement(webdriver.By.css('shop-app /deep/ app-header')); 

// This fails because: 
// NoSuchElementError: no such element: Unable to locate element 
driver.findElement(webdriver.By.css('shop-app::shadow app-header')); 

// This fails because: 
// TypeError: Custom locator did not return a WebElement 
driver.findElement(webdriver.By.js(function() { 
    return document.querySelector('shop-app /deep/ app-header'); 
})); 

// This fails because: 
// TypeError: Custom locator did not return a WebElement 
driver.findElement(webdriver.By.js(function() { 
    return document.querySelector('shop-app::shadow app-header'); 
})); 

// This fails because: 
// WebDriverError: unknown error: Cannot read property 'querySelector' of null 
driver.findElement(webdriver.By.js(function() { 
    return document.querySelector('shop-app').shadowRoot.querySelector('app-header'); 
})); 

// This fails because: 
// WebDriverError: unknown error: Cannot read property 'header' of undefined 
driver.findElement(webdriver.By.js(function() { 
    return document.querySelector('shop-app').$.header; 
})); 

Я бег узла 7.1.0 и селен WebDriver 3.0.1.

ответ

2

Вы должны использовать метод driver.executeScript().

Затем войдите в Теневой ДОМ с «клиентом» Javascript.

Посмотрите на этот пример в another SO answer.

2

Я думаю, что лучше использовать селеновые селекторы и впрыснуть сценарий просто взять тень корня:

def expand_shadow_element(element): 
    shadow_root = driver.execute_script('return arguments[0].shadowRoot', element) 
    return shadow_root 

outer = expand_shadow_element(driver.find_element_by_css_selector("#test_button")) 
inner = outer.find_element_by_id("inner_button") 
inner.click() 

Чтобы поместить это в перспективе я просто добавил проверяемой пример с загрузки страницы в Chrome, нажав на поиск потребности кнопки открытые 3 гнездовых тень корневых элементов: enter image description here

import selenium 
from selenium import webdriver 
driver = webdriver.Chrome() 


def expand_shadow_element(element): 
    shadow_root = driver.execute_script('return arguments[0].shadowRoot', element) 
    return shadow_root 

driver.get("chrome://downloads") 
root1 = driver.find_element_by_tag_name('downloads-manager') 
shadow_root1 = expand_shadow_element(root1) 

root2 = shadow_root1.find_element_by_css_selector('downloads-toolbar') 
shadow_root2 = expand_shadow_element(root2) 

root3 = shadow_root2.find_element_by_css_selector('cr-search-field') 
shadow_root3 = expand_shadow_element(root3) 

search_button = shadow_root3.find_element_by_css_selector("#search-button") 
search_button.click() 

Doing тот же подход, предложенными в других ответах имеет тот недостаток, что это трудно-кода запросов, является менее читаемым и вы ч nnot использовать промежуточные выборы для других действий:

search_button = driver.execute_script('return document.querySelector("downloads-manager").shadowRoot.querySelector("downloads-toolbar").shadowRoot.querySelector("cr-search-field").shadowRoot.querySelector("#search-button")') 
search_button.click() 
+1

Один из лучших Ответов, которые я видел на SO (+1) – DebanjanB