简体   繁体   中英

How to click and select element within async function page.evalue in pupeteer

Trying to iterate over invalid fields and entering/selecting values on the page.

const enterTextFields = async (page) => {
  const txtQuestText = await page.evaluate(() =>
    Array.from(
      document.querySelectorAll('div[aria-invalid="true"]'),
      async (element) => {
        const span = element.querySelector(
          'label span[data-test-form-element-label-title="true"]'
        );
        const ques = span.textContent.trim();
        const ans = await window.getAns(ques);
        if (ans) {
          const txtField = element.querySelector('div input[type="text"]');
          if (txtField) {
            txtField.type(ans);
          }
          const dropdownField = element.querySelector(
            "div select[data-test-fb-dropdown-select]"
          );
          if (dropdownField) {
            dropdownField.select(ans);
          }
        }
        return ques + " : " + ans;
      }
    )
  );
  console.log("txtQuestText : ", txtQuestText);
}

On the execution of the above page.evaluate , neither text nor dropdown field is getting filled even though there are ans available for the ques .

In txtQuestText getting:

(2) [{…}, {…}]
0: {}
1: {}
length: 2
[[Prototype]]: Array(0)
[[Prototype]]: Object

If I remove async from async (element) => { , await window.getAns(ques) call and if block then I can see the list of correct Ques strings in txtQuestText .

Cannot remove async due to await window.getAns(ques) .

Not sure what is going wrong and or how to use it. Please Help!

I can't run your code, but the problem appears to be returning an array from evaluate rather than a single promise object. Puppeteer isn't smart enough to realize this is an array of promises, so it doesn't resolve them. The promises degrade into empty objects once they pass through the serialization/deserialization process.

Here's a reproducible example:

const puppeteer = require("puppeteer"); // ^18.0.4

let browser;
(async () => {
  browser = await puppeteer.launch();
  const [page] = await browser.pages();
  const html = "<html><body><p>test</p><p>test2</p></body></html>";
  await page.setContent(html);

  const result = await page.evaluate(() =>
    Array.from(
      document.querySelectorAll("p"),
      async el => el.textContent // pretend we need to await in this func
    )
  );

  console.log(result); // => [ {}, {} ]
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close())
;

The fix is to return a single promise rather than an array of promises:

const puppeteer = require("puppeteer"); // ^18.0.4

let browser;
(async () => {
  browser = await puppeteer.launch();
  const [page] = await browser.pages();
  const html = "<html><body><p>test</p><p>test2</p></body></html>";
  await page.setContent(html);

  const result = await page.evaluate(() =>
    Promise.all(Array.from(
      document.querySelectorAll("p"),
      async el => el.textContent
    ))
  );

  console.log(result); // => [ 'test', 'test2' ]
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close())
;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM