mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
feat(ElementHandle): add ElementHandle.$ and ElementHandle.$$ (#1151)
This patch adds `ElementHandle.$` and `ElementHandle.$$` methods to query nested elements. Fixes #508
This commit is contained in:
parent
9e39f5f8a6
commit
5ffbd0d221
16
docs/api.md
16
docs/api.md
@ -145,6 +145,8 @@
|
||||
* [jsHandle.getProperty(propertyName)](#jshandlegetpropertypropertyname)
|
||||
* [jsHandle.jsonValue()](#jshandlejsonvalue)
|
||||
- [class: ElementHandle](#class-elementhandle)
|
||||
* [elementHandle.$(selector)](#elementhandleselector)
|
||||
* [elementHandle.$$(selector)](#elementhandleselector)
|
||||
* [elementHandle.asElement()](#elementhandleaselement)
|
||||
* [elementHandle.boundingBox()](#elementhandleboundingbox)
|
||||
* [elementHandle.click([options])](#elementhandleclickoptions)
|
||||
@ -1720,8 +1722,20 @@ ElementHandle prevents DOM element from garbage collection unless the handle is
|
||||
|
||||
ElementHandle instances can be used as arguments in [`page.$eval()`](#pageevalselector-pagefunction-args) and [`page.evaluate()`](#pageevaluatepagefunction-args) methods.
|
||||
|
||||
#### elementHandle.$(selector)
|
||||
- `selector` <[string]> A [selector] to query element for
|
||||
- returns: <[Promise]<[ElementHandle]>>
|
||||
|
||||
The method runs `element.querySelector` within the page. If no element matches the selector, the return value resolve to `null`.
|
||||
|
||||
#### elementHandle.$$(selector)
|
||||
- `selector` <[string]> A [selector] to query element for
|
||||
- returns: <[Promise]<[Array]<[ElementHandle]>>>
|
||||
|
||||
The method runs `element.querySelectorAll` within the page. If no elements match the selector, the return value resolve to `[]`.
|
||||
|
||||
#### elementHandle.asElement()
|
||||
- returns: <[ElementHandle]>
|
||||
- returns: <[elementhandle]>
|
||||
|
||||
#### elementHandle.boundingBox()
|
||||
- returns: <[Object]>
|
||||
|
@ -147,6 +147,42 @@ class ElementHandle extends JSHandle {
|
||||
clip: boundingBox
|
||||
}, options));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} selector
|
||||
* @return {!Promise<?ElementHandle>}
|
||||
*/
|
||||
async $(selector) {
|
||||
const handle = await this.executionContext().evaluateHandle(
|
||||
(element, selector) => element.querySelector(selector),
|
||||
this, selector
|
||||
);
|
||||
const element = handle.asElement();
|
||||
if (element)
|
||||
return element;
|
||||
await handle.dispose();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} selector
|
||||
* @return {!Promise<!Array<!ElementHandle>>}
|
||||
*/
|
||||
async $$(selector) {
|
||||
const arrayHandle = await this.executionContext().evaluateHandle(
|
||||
(element, selector) => element.querySelectorAll(selector),
|
||||
this, selector
|
||||
);
|
||||
const properties = await arrayHandle.getProperties();
|
||||
await arrayHandle.dispose();
|
||||
const result = [];
|
||||
for (const property of properties.values()) {
|
||||
const elementHandle = property.asElement();
|
||||
if (elementHandle)
|
||||
result.push(elementHandle);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ElementHandle;
|
||||
|
37
test/test.js
37
test/test.js
@ -1718,6 +1718,43 @@ describe('Page', function() {
|
||||
}));
|
||||
});
|
||||
|
||||
describe('ElementHandle.$', function() {
|
||||
it('should query existing element', SX(async function() {
|
||||
await page.goto(PREFIX + '/playground.html');
|
||||
await page.setContent('<html><body><div class="second"><div class="inner">A</div></div></body></html>');
|
||||
const html = await page.$('html');
|
||||
const second = await html.$('.second');
|
||||
const inner = await second.$('.inner');
|
||||
const content = await page.evaluate(e => e.textContent, inner);
|
||||
expect(content).toBe('A');
|
||||
}));
|
||||
|
||||
it('should return null for non-existing element', SX(async function() {
|
||||
await page.setContent('<html><body><div class="second"><div class="inner">B</div></div></body></html>');
|
||||
const html = await page.$('html');
|
||||
const second = await html.$('.third');
|
||||
expect(second).toBe(null);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('ElementHandle.$$', function() {
|
||||
it('should query existing elements', SX(async function() {
|
||||
await page.setContent('<html><body><div>A</div><br/><div>B</div></body></html>');
|
||||
const html = await page.$('html');
|
||||
const elements = await html.$$('div');
|
||||
expect(elements.length).toBe(2);
|
||||
const promises = elements.map(element => page.evaluate(e => e.textContent, element));
|
||||
expect(await Promise.all(promises)).toEqual(['A', 'B']);
|
||||
}));
|
||||
|
||||
it('should return empty array for non-existing elements', SX(async function() {
|
||||
await page.setContent('<html><body><span>A</span><br/><span>B</span></body></html>');
|
||||
const html = await page.$('html');
|
||||
const elements = await html.$$('div');
|
||||
expect(elements.length).toBe(0);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('input', function() {
|
||||
it('should click the button', SX(async function() {
|
||||
await page.goto(PREFIX + '/input/button.html');
|
||||
|
Loading…
Reference in New Issue
Block a user