Gojira
Gojira

Reputation: 3041

puppeteer - page.type() doesn't work but element.setAttribute() does?

I want to use Puppeteer to enter a value in an input field. According to the documentation, this seems straightforward (examples from docs):

await page.type('#mytextarea', 'Hello'); // Types instantly
await page.type('#mytextarea', 'World', {delay: 100}); // Types slower, like a user

So I've created the following test script:

const puppeteer = require('puppeteer');

(async () => {

  const browser = await puppeteer.launch({headless: false}); // devtools: true
  const page = await browser.newPage();
  await page.goto('https://mycoolsite/index.html');

  page.on('console', msg => console.log(new Date().toISOString() + ' ' + msg._text));

  const selector = '#barcode';
  await page.waitForSelector(selector);
  await page.type(selector, "1234");

})();

It works up to the page.type() line. Meaning, it launches an instance of Chromium, goes to the correct URL, displays the expected output from the console in the log. But does not type a value in the field. I'm not seeing any errors in either the node output or the browser console output.

To rule out a silent failure, I changed the selector name to something that doesn't exist (e.g., "#qwertyuiop") and got a failure as expected.

I found a workaround if I replace the line await page.type(selector, "1234"); with the following:

  const element = await page.$(selector);
  await page.evaluate(element => { element.setAttribute('value', 1234); }, element);

That feels like a hack. Why does puppeteer correctly set the value with page.evaluate but not the documented page.type method?

Upvotes: 2

Views: 10773

Answers (2)

bibscy
bibscy

Reputation: 2708

  const selector = '#barcode';
  await page.waitForSelector(selector);
  await page.focus(selector); //you need to focus on the textField
  await page.keyboard.type(selector, "1234"); //you are also missing  keyboard  property

Upvotes: 1

Gojira
Gojira

Reputation: 3041

Figured it out...

The input was contained by a hidden element.

Changing the line

await page.waitForSelector(selector);

to

await page.waitForSelector(selector, {visible: true, timeout: 3000 });

solved it. Apparently an element has to be visible before page.type() will work, whereas setting the element's value via attribute doesn't care as long as it's part of the DOM.

(From the docs - the visible option causes puppeteer to wait for element to be present in DOM and to be visible. Defaults to false.)

Upvotes: 5

Related Questions