I have a pretty simple use case here, I need to go through a table of elements and click on each one, and enter a value.
In the browser environment, you can call the QuerySelector on document, and any node. So you can do something easily like :
const list = document.querySelectorAll('.rows')
And then query elements from each row with
list.map(el => {
el.querySelector('.thing_1').click();
el.querySelector('.thing_2').click();
el.querySelector('.thing_3').click();
})
I'm using the list element el as the root of the QuerySelector to get the 2nd level elements.
So now I'm in a situation where the Javascript Click function does not work correctly, and I need to mouse click. In puppeteer I believe you need to do this by calling the page.click() method, which Page is not available in the Browser level context (ie: within page.evaluate() or $$eval() )
I know I can get the elements of the nodes the same way as QuerySelectorAll with the const list = page.$$('.rows')
function, But once I have that, How do I iterate through them to query the 2nd level elements FROM the node as the root element of the next query? Is it even possible in the puppeteer context?
As you might guess, you can't just go
page.click('.thing_1');
Because that query will just give you the thing_1 of the First Row, and there's not really a good way to query select the current row besides using the existing element node. Ideally you'd like to css query in the same way to do something like
list.map((el,page) => {
page.click(el.querySelector('.thing_1'));
...
},page)
Is this even possible? If so what's the correct syntax for it? Every answer I've seen on this type of question effectively uses the Javascript Click function and not the Puppeteer click function.
I figured this out thanks to another answer while I was testing. In case anyone else struggles with this :
JAVASCRIPT BROWSER CONTEXT
const rows = document.QuerySelectorAll(".row")
const data = rows.map(r=>r.querySelector(".item_in_row").innerText);
PUPPETEER CONTEXT:
const rows = await page.$$(".row");
let data = [];
for(let r of rows) {
const item = await r.$(".item_in.row");
const item_in_row_text = await item.evaluate(x => x.innerText);
data.push(item_in_row_text);
}
JS document.QuerySelectorAll() == Puppeteer page.$$() JS document.QuerySelector() == Puppeteer page.$() You can run the same .$() and .$$() functions (as well as evaluate and other page functions) on Array of CdpElementHandle objects returned from the page.$$() function like you can on NodeList of elements returned by document.querySelectorAll().
Also, I believe calling the .click() function in the puppeteer context on a CdpElementHandle object will perform a Puppeteer click much like page.click(selector) , as opposed to the javascript click function. My issue was getting the 2nd level handle of the table objects in the puppeteer context in the first place.