How to select a dropdown option by text in Puppeteer?

I’m trying to create a custom function in Puppeteer to select a dropdown option based on its text, not its value. Here’s what I’ve come up with:

async function pickDropdownOption(page, dropdownSelector, optionText) {
  await page.evaluate(({ selector, text }) => {
    const dropdown = document.querySelector(selector);
    const options = dropdown.options;
    for (let option of options) {
      if (option.text === text) {
        dropdown.value = option.value;
        break;
      }
    }
  }, { selector: dropdownSelector, text: optionText });
}

However, it’s not working as expected. When I try to log the selected options, I get a weird output:

{"0":{"0":{},"1":{},"2":{},"3":{}}}

Can anyone help me understand what’s going wrong and how to fix it? I’m new to Puppeteer and could use some guidance on this. Thanks!

I’ve dealt with similar challenges when working with Puppeteer. One approach that’s worked well for me is using the page.$eval method. It allows you to execute a function in the context of the page and return a result. Here’s a modified version of your function that might solve the issue:

async function pickDropdownOption(page, dropdownSelector, optionText) {
  await page.$eval(dropdownSelector, (select, text) => {
    const option = Array.from(select.options).find(opt => opt.text === text);
    if (option) {
      select.value = option.value;
      select.dispatchEvent(new Event('change', { bubbles: true }));
    }
  }, optionText);
}

This approach combines the best of both worlds - it’s efficient and ensures the change event is triggered. It should resolve the weird output you’re seeing. Remember to handle cases where the option might not exist to avoid potential errors.

I’ve encountered a similar issue before, and I found that using the select-option API provided by Puppeteer works more reliably. Here’s an approach that might solve your problem:

async function pickDropdownOption(page, dropdownSelector, optionText) {
  await page.select(dropdownSelector, await page.evaluate((selector, text) => {
    const select = document.querySelector(selector);
    const option = Array.from(select.options).find(opt => opt.text === text);
    return option ? option.value : null;
  }, dropdownSelector, optionText));
}

This method uses page.select() which handles both the value change and event dispatching. It’s also more efficient as it only needs one page.evaluate call. Give it a try and see if it resolves your issue. Let me know if you need any further clarification!

hey alexlee, lemme try to help ya out. ur code looks mostly good, but it might not be triggering the change event. try adding this after setting the value:

dropdown.dispatchEvent(new Event(‘change’, { bubbles: true }));

that should make the browser recognize the selection. hope it helps!