问题
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