如何为 Polymer 元素 shadow dom 元素指定选择器?
How to specify selector for Polymer elements shadow dom elements?
我有一个基于 Polymer 的 Web 应用程序,我想用 Puppeteer 对其进行测试。
当多个 Polymer 组件相互嵌入时,编写选择器的合适方法是什么?
布局为:
app > comp1 > comp2 > target_element
所有的“>”标记了一个新的阴影 dom 边界。
如果我想测试链末端的 target_element,正确的选择器是什么?
事实证明,并不是easy to select element in shadow dom. Achim Weimert show some workaround to get pierce select through shadow dom. His method works for app-header
in https://shop.polymer-project.org/:
const puppeteer = require('puppeteer');
const shadowSelectorFn = (el, selector) => el.shadowRoot.querySelector(selector);
const queryDeep = async (page, ...selectors) => {
if (!selectors || selectors.length === 0) {
return;
}
const [ firstSelector, ...restSelectors ] = selectors;
let parentElement = await page.$(firstSelector);
for (const selector of restSelectors) {
parentElement = await page.evaluateHandle(shadowSelectorFn, parentElement, selector);
}
return parentElement;
};
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://shop.polymer-project.org/');
const app = await page.$('shop-app');
console.log(app);
// you can not simply wait for element inside shadow dom
// it's up to you how you detect if this element is ready
await page.waitFor(2000);
const header = await queryDeep(
page,
'shop-app', 'app-header'
);
console.log(header);
await browser.close();
})();
值得一提的是,没有简单的方法可以检测 app-header
元素何时准备就绪。您可以在一定时间间隔内循环检查此元素,或者您应该寻找其他解决方案。
我有一个基于 Polymer 的 Web 应用程序,我想用 Puppeteer 对其进行测试。
当多个 Polymer 组件相互嵌入时,编写选择器的合适方法是什么?
布局为:
app > comp1 > comp2 > target_element
所有的“>”标记了一个新的阴影 dom 边界。
如果我想测试链末端的 target_element,正确的选择器是什么?
事实证明,并不是easy to select element in shadow dom. Achim Weimert show some workaround to get pierce select through shadow dom. His method works for app-header
in https://shop.polymer-project.org/:
const puppeteer = require('puppeteer');
const shadowSelectorFn = (el, selector) => el.shadowRoot.querySelector(selector);
const queryDeep = async (page, ...selectors) => {
if (!selectors || selectors.length === 0) {
return;
}
const [ firstSelector, ...restSelectors ] = selectors;
let parentElement = await page.$(firstSelector);
for (const selector of restSelectors) {
parentElement = await page.evaluateHandle(shadowSelectorFn, parentElement, selector);
}
return parentElement;
};
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://shop.polymer-project.org/');
const app = await page.$('shop-app');
console.log(app);
// you can not simply wait for element inside shadow dom
// it's up to you how you detect if this element is ready
await page.waitFor(2000);
const header = await queryDeep(
page,
'shop-app', 'app-header'
);
console.log(header);
await browser.close();
})();
值得一提的是,没有简单的方法可以检测 app-header
元素何时准备就绪。您可以在一定时间间隔内循环检查此元素,或者您应该寻找其他解决方案。