Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I navigate dom elements in puppeteer?

Background

We are writing some automated end to end tests with puppeteer for the first time. We've been digging through their APIs at great length, but we're stumped and struggling with what feels to us like basic uses for the system.

The Real Question

How does puppeteer want us to interact with the elements?

  • get their attributes
  • set stuff on them
  • find specific ancestors and descendants of them

Comments

What I really want is either a more trimmed API document targeted at our kinds of uses or, even better, a really slick tutorial. We've looked at quite a lot, but we just aren't getting these sorts of answers yet.

What all the guides we have found are doing, that we do not want to do, is manually putting into the code lots and lots of IDs and selectors. I understand why, but for our purposes we want to read from what is on the page and generate our behavior based on it's shape.

Thanks for your time!

Extra Credit

How should I actually approach these code snippets? What methods/structures?

Here's one that wants to type a string into all the text inputs, but gets the values for all inputs.

const nodeList = await page.$$('input');
const result = nodeList.map(async node => {
    if(node.type === 'text'){
        await node.type('2018');
    }
    return await node.getAttribute('value')
})
return result

Here's one that wants to type a span label into any child input within that span's parent div.

const nodeList = await page.$$('span');
const result = nodeList.map(async node => {
    const parentDiv = node.NearestAncestor('div')
    const inputs = parentDiv.$$('input')
    **Use Code From Above**
})
return result
like image 295
Suni Avatar asked Jan 02 '23 05:01

Suni


1 Answers

You can try to wrap your promises inside a Promise.all.

So instead of returning result, you return Promise.all(result) which will resolve once it get's all of the data.

Also, there are many different ways to go thru the list or selectors.

$$eval

This runs Array.from(document.querySelectorAll(selector)) within the page and passes it as the first argument to pageFunction.

Example code:

await page.$$eval('a', a => a.href)

evaluate

This is golden and you can execute any code that you can execute on your browsers console.

const result = await page.evaluate(() =>
  [...document.querySelectorAll('input')] // or anything that you want to use normally
)

Useful APIs

There are several useful APIs that can be used wisely:

  • .type: types a text on selector
  • .click: Clicks an elementhandle/selector etc
  • .select: Selects something from a element

Know what doesn't work

elementHandle.attribute() has been removed on #638. Which means getting attribute should be handled by $eval from now.

like image 179
Md. Abu Taher Avatar answered Jan 05 '23 17:01

Md. Abu Taher