I need to create a custom function that selects dropdown options based on their text content rather than values since puppeteer doesn’t have a built-in method for this.
async function chooseDropdownByText(browser, elementSelector, textContent) {
return await browser.evaluate((params) => {
console.log('Parameters:', JSON.stringify(params));
let dropdownOptions = document.querySelectorAll(params.elementSelector);
console.log('Found options:', JSON.stringify(dropdownOptions));
let totalOptions = dropdownOptions.length;
for (let index = 0; index < totalOptions; ++index) {
if (dropdownOptions[index].text === params.textContent) {
console.log('Found matching option');
document.querySelector(params.elementSelector).value = dropdownOptions[index].value;
}
}
}, {elementSelector, textContent})
}
The function isn’t working as expected. When I check the console output for the selected options, I get this weird result:
{“0”:{“0”:{},“1”:{},“2”:{},“3”:{}}}
Can someone help me figure out what’s going wrong here and how to fix it?
The issue arises because querySelectorAll returns a NodeList, which cannot be directly serialized, leading to that unexpected output. Additionally, your function only changes the value of the first matching option and does not trigger the change event. Here’s how you can correct the code:
async function chooseDropdownByText(page, elementSelector, textContent) {
return await page.evaluate((selector, text) => {
const dropdown = document.querySelector(selector);
if (!dropdown) return false;
const options = Array.from(dropdown.options);
const targetOption = options.find(option => option.text.trim() === text.trim());
if (targetOption) {
dropdown.value = targetOption.value;
dropdown.dispatchEvent(new Event('change', { bubbles: true }));
return true;
}
return false;
}, elementSelector, textContent);
}
This version uses page.evaluate instead of browser.evaluate and converts the options to an array before searching for the target option.
that strange output is likely due to NodeList’s stringify issue. use page.evaluate rather than browser.evaluate. also, switch to textContent instead of text; it could help. remember to dispatch the change event too, else the dropdown won’t refresh!
The unusual console output occurs because querySelectorAll returns a NodeList, which doesn’t serialize well to JSON. Also, you’re trying to access the elements incorrectly within the dropdown. Here’s a solution that should work for you:
async function chooseDropdownByText(page, elementSelector, textContent) {
return await page.evaluate((selector, text) => {
const dropdownElement = document.querySelector(selector);
if (!dropdownElement) return false;
const options = Array.from(dropdownElement.options);
const targetOption = options.find(option => option.textContent.trim() === text.trim());
if (targetOption) {
dropdownElement.value = targetOption.value;
dropdownElement.dispatchEvent(new Event('change', { bubbles: true }));
return true;
}
return false;
}, elementSelector, textContent);
}
Key changes: directly access the options property of the select element and trigger the change event after setting the value.