Escaping using encoded data
If you even try to do document.querySelector('#fruit[0]')
on your browser, you will get same error. The escape doesn't work because by the time puppeteer reads it, it is already parsed and doesn't have the same escaped value. Few ways to escape them.
Say we have an element like this,
<a href="/" id="sample[112]">Bar</a>
Now if you want to use vanila JS, you can try the following,

Which reads the following:
< document.querySelector(CSS.escape('#sample[112]'))
> null
< document.querySelector('#sample[112]')
> Uncaught DOMException: Failed to execute 'querySelector' on 'Document': '#sample[112]' is not a valid selector.
< document.querySelector('#sample\5b 112\5d')
> ncaught DOMException: Failed to execute 'querySelector' on 'Document': '#sampleb 112d' is not a valid selector.
< document.querySelector('#sample\\5b 112\\5d')
> <a href="/" id="sample[112]">Bar</a>
As you can see above, the left bracket is 5b
and right bracket is 5d
, and we even had to escape that and had to put space so browser could parse it.
You should try out above codes and find which one works for your site.
Real case scripts
Let's face it, your target website does not have value for the options. The best way will be to select by text, shamelessly copying from this answer.
Also, I could escape it twice and get data without encoding them. After all, nodeJS is different than the browsers console, and everything will act differently when on a script.
Source used for HTML,
<select id="sample[1]"><option>mango</option><option>apple</option></select>
And puppeteer code used for testing,
const puppeteer = require("puppeteer");
function setSelectByText(selector, text) {
// Loop through sequentially//
const ele = document.querySelector(selector);
console.log(ele);
for (let ii = 0; ii < ele.length; ii++) {
if (ele.options[ii].text == text) {
// Found!
ele.options[ii].selected = true;
return true;
}
}
return false;
}
puppeteer.launch().then(async browser => {
console.log("Opening browser");
const page = await browser.newPage();
console.log("Going to site");
await page.goto("http://0.0.0.0:8080"); // temporary website created for testing
await page.evaluate(setSelectByText, "#sample\\[1\\]", "apple"); // we can use this over and over, without creating a separate function, just passing them as arguments
await page.screenshot({ path: "test.png" });
await browser.close();
});
