Node puppeteer how to type into a list of input elements

Viewed 262

I'm trying to recreate this bot I made in python to go through a Google form, fill it out and submit. The way in python was to collect all the input tags into a list, then just loop over then with another list to type in all the text I wanted. But in puppeteer I cant seem to do the same.

const run = async () => {

const width = 1000
const height = 1000

const browser = await pup.launch({
    headless: false,
    defaultViewport: {
        width,
        height
    }
});

const [page] = await browser.pages();
await page.goto('https://docs.google.com/forms/d/e/1FAIpQLSdJfQRqH7JmtzrkwPId2Vth3pteB90KYNnqeYpz_hO6i4_ug/viewform')

const input = await page.waitForSelector('input.whs0nd.zHQkBf');
await inn.type('hello')
await page.$$eval('input.whsOnd.zHQkBf', inputs => inputs.forEach(x => {
    x.type('hello')
}))

}

run()

In the line with waitForSelector I am trying to wait till the first input element is visible then type into that but I just keep getting a timeout error as seen below.

node app.js
C:\Users\carjames\OneDrive - Cisco\Documents\Code\puppeteer 
TUT\node_modules\puppeteer\lib\cjs\puppeteer\common\DOMWorld.js:528
        const timeoutError = new Errors_js_1.TimeoutError(`waiting for ${options.title} 
failed: timeout ${options.timeout}ms exceeded`);
                             ^

TimeoutError: waiting for selector `input.whs0nd.zHQkBf` failed: timeout 30000ms exceeded
    at new WaitTask (C:\Users\carjames\OneDrive - Cisco\Documents\Code\puppeteer 
TUT\node_modules\puppeteer\lib\cjs\puppeteer\common\DOMWorld.js:528:34)
    at DOMWorld.waitForSelectorInPage (C:\Users\carjames\OneDrive - 
Cisco\Documents\Code\puppeteer 
TUT\node_modules\puppeteer\lib\cjs\puppeteer\common\DOMWorld.js:432:26)        
    at Object.internalHandler.waitFor (C:\Users\carjames\OneDrive - 
Cisco\Documents\Code\puppeteer 
TUT\node_modules\puppeteer\lib\cjs\puppeteer\common\QueryHandler.js:31:77)     
    at DOMWorld.waitForSelector (C:\Users\carjames\OneDrive - Cisco\Documents\Code\puppeteer 
TUT\node_modules\puppeteer\lib\cjs\puppeteer\common\DOMWorld.js:323:29)
    at Frame.waitForSelector (C:\Users\carjames\OneDrive - Cisco\Documents\Code\puppeteer 
TUT\node_modules\puppeteer\lib\cjs\puppeteer\common\FrameManager.js:942:51)
    at Page.waitForSelector (C:\Users\carjames\OneDrive - Cisco\Documents\Code\puppeteer 
TUT\node_modules\puppeteer\lib\cjs\puppeteer\common\Page.js:2359:33)
    at run (C:\Users\carjames\OneDrive - Cisco\Documents\Code\puppeteer TUT\app.js:30:28)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

Node.js v17.6.0

I also tried to loop through all the input elements in the commented out lines. That also didn't work. I just kept getting x.type is not a function. As seen below.

node app.js
C:\Users\carjames\OneDrive - Cisco\Documents\Code\puppeteer 
TUT\node_modules\puppeteer\lib\cjs\puppeteer\common\ExecutionContext.js:221
        throw new Error('Evaluation failed: ' + 
helper_js_1.helper.getExceptionMessage(exceptionDetails));
              ^

Error: Evaluation failed: TypeError: x.type is not a function
    at __puppeteer_evaluation_script__:2:11
    at Array.forEach (<anonymous>)
    at __puppeteer_evaluation_script__:1:19
    at ExecutionContext._evaluateInternal (C:\Users\carjames\OneDrive - 
Cisco\Documents\Code\puppeteer 
TUT\node_modules\puppeteer\lib\cjs\puppeteer\common\ExecutionContext.js:221:19)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async ExecutionContext.evaluate (C:\Users\carjames\OneDrive - 
Cisco\Documents\Code\puppeteer 
TUT\node_modules\puppeteer\lib\cjs\puppeteer\common\ExecutionContext.js:110:16)
    at async JSHandle.evaluate (C:\Users\carjames\OneDrive - Cisco\Documents\Code\puppeteer 
TUT\node_modules\puppeteer\lib\cjs\puppeteer\common\JSHandle.js:103:16)
    at async ElementHandle.$$eval (C:\Users\carjames\OneDrive - Cisco\Documents\Code\puppeteer 
TUT\node_modules\puppeteer\lib\cjs\puppeteer\common\JSHandle.js:844:24)
    at async DOMWorld.$$eval (C:\Users\carjames\OneDrive - Cisco\Documents\Code\puppeteer 
TUT\node_modules\puppeteer\lib\cjs\puppeteer\common\DOMWorld.js:124:23)
    at async run (C:\Users\carjames\OneDrive - Cisco\Documents\Code\puppeteer TUT\app.js:32:5)

Node.js v17.6.0

Please Help

1 Answers

This is a common Puppeteer mistake, assuming that the callback to eval runs in Puppeteer/Node context, when the code is actually executing the code in the browser console. As the error tells you, HTMLElement.type is not a browser method. That's a Puppeteer/Node ElementHandle method.

Your options are:

  1. Select the elements in Puppeteer as ElementHandles using page.$$(...), then loop over them and call handle.type("hello") on each.

  2. Run an evaluate or eval callback and use native browser code to fill out the inputs, e.g. x.value = "hello", and optionally trigger event handler(s) with x.dispatchEvent(new Event("change")).

    After seeing the Google form, it turns out this second method won't work, probably because the events aren't trusted (although I didn't research it deeply). That leaves option #1.

As an aside, inn.type('hello') doesn't seem like it'll work since inn was never defined and input.whs0nd.zHQkBf should be input.whsOnd.zHQkBf (notice O instead of 0), so I suspect this isn't your actual code.

Related