How can I consistently fill out input fields?

一世执手 提交于 2019-12-13 03:42:25

问题


I'm not sure why, but it seems like some fields just don't work for me.

This is working fine for me on one site:

await page.click(USERNAME_SELECTOR);
await page.keyboard.type(CREDS.username);
await page.click(PASSWORD_SELECTOR);
await page.keyboard.type(CREDS.password);
await page.click(LOGIN_BUTTON_SELECTOR);
await page.waitForNavigation();

However, on https://app.member.virginpulse.com/, it doesn't seem to work for me. It should be simple enough as the input fields both have IDs (#username and $password)... however, it just doesn't seem to fill out properly.

const puppeteer = require('puppeteer');
const email = "foo@bar.com";
const password = "foopass";
const emailInputSel = "#username";
const passwordInputSel = "#password";
const signInButtonSel = ".login-submit input";
const homeUrl = "https://app.member.virginpulse.com";

async function run() {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto(homeUrl, {waitUntil: 'domcontentloaded'});
    //----from here---
    await page.waitFor(emailInputSel);
    await page.$eval(emailInputSel, (e,v) => e.value = v, email);
    await page.$eval(passwordInputSel, (e,v) => e.value = v, password);
    //----to here----- i've tried several things
    await page.screenshot({path: 'screenshot.png'});
    ...

Other things I've tried:

await page.evaluate((sel, val) => {
    const ele = document.querySelector(sel);
    if (!ele) {
        return;
    }
    ele.value = val;
}, sel, val);

await page.evaluate((sel) => {
    const ele = document.querySelector(sel);
    if (!ele) {
        return;
    }
    ele.click(); ele.focus();
}, sel);
await page.keyboard.type(val);

Nothing seems to fill out the data properly. Does anyone know what is happening and how to get this to work?


回答1:


Fix 1: Wait until element is VISIBLE

Just waiting for selector will not work, we must wait till the element is properly visible on the viewport and navigation requests are done.

// wait until all requests are done
await page.goto(homeUrl, { waitUntil: "networkidle0" });

// wait until the email selector is visible on viewport
await page.waitForSelector(emailInputSel, { visible: true }); 

Just adding above changes on your current code gave me this result,

Notice how the result screenshot above does not have any content on the submit button, same happens with your other selectors as well.

Fix 2: Pass the data properly

This is optional in case the first fix does not change anything.

Step 1

Instead of passing two arguments, pass one argument with braces.

await page.evaluate((sel, val) => {
    const ele = document.querySelector(sel);
    if (!ele) {
        return;
    }
    ele.value = val;
}, (sel, val)); // <-- Look here

Step 2

If the above step 1 does not work, then try to trigger the change. So if it's a angular app, it should know that the element has changed, Change the above to this,

await page.evaluate((sel, val) => {
  const ele = document.querySelector(sel);
  if (!ele) {
    return;
  }
  ele.value = val;

  // Trigger the change here
  var event = new Event('input', {
    'bubbles': true,
    'cancelable': true
  });

  ele.dispatchEvent(event);

}, (sel, val));

Optional

If you want to reuse the same thing multiple time, you can rewrite them in this manner,

const fillInput = (sel, val) => {
  await page.waitForSelector(sel, { visible: true });
  await page.evaluate((sel, val)=>{}) // the code from above function should be here
}

then call like this,

await fillInput(emailInputSel, email)


来源:https://stackoverflow.com/questions/56282543/how-can-i-consistently-fill-out-input-fields

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!