Reputation: 78
I'm trying to enter text into an input field using Puppeteer.
async function reddit() {
const broswer = await puppeteer.launch({
headless: false
})
const page = await broswer.newPage();
const navPromise = page.waitForNavigation({
waitUntil: 'domcontentloaded'
})
await page.goto('https://www.reddit.com/r/place/?cx=352&cy=522&px=69')
await navPromise;
console.log('did i get this far? 1');
await page.click('a._3Wg53T10KuuPmyWOMWsY2F:nth-child(2)')
await navPromise;
console.log('did i get this far?2 ');
await page.keyboard.type('#loginUsername', 'hjello')
console.log('did i get this far?3');
}
reddit()
I get all three console logs when it runs. I can see it click on the username log in but it doesn't type anything. I have looked at multiple StackOverflow questions and tried the answers but none of them will type the input in.
Upvotes: 1
Views: 3533
Reputation: 56965
await page.click('a._3Wg53T10KuuPmyWOMWsY2F:nth-child(2)')
triggers a DOM change, but then immediately fires .click()
on an element that might not be ready yet, so that looks like a race condition. I suggest using waitForSelector
(or waitForNavigation
if a navigation is triggered, which doesn't appear to be the case here).
const navPromise = page.waitForNavigation({waitUntil: 'domcontentloaded'})
is in a strange location above a goto
which already waits for navigation, then it's await
ed twice, which doesn't make sense. Once a promise is resolved, it'll never be resolved again, so the only time you'd want to do this is if you need to access the resolved value again, which doesn't apply here. Waiting for extra navigations can cause a timeout when one isn't triggered.
The main issue, though, appears to be that the selector you're trying to type into is inside an iframe. It's possible to dive into this frame and set the value, but it's much easier to save all the trouble and navigate directly to the login page frame URL, log in, then navigate with a goto
to whatever page you're trying to get to.
For example:
const puppeteer = require("puppeteer"); // ^13.5.1
let browser;
(async () => {
browser = await puppeteer.launch({headless: false});
const [page] = await browser.pages();
const url = "https://www.reddit.com/login/";
await page.goto(url, {waitUntil: "domcontentloaded"});
await page.waitForSelector("#loginUsername");
await page.type("#loginUsername", "hjello");
await page.type("#loginPassword", "foobar");
await Promise.all([
page.waitForNavigation(),
page.click(".AnimatedForm__submitButton"),
]);
// navigate to wherever you want with page.goto
})()
.catch(err => console.error(err))
.finally(() => browser?.close())
;
Note that when you're selecting elements in the browser console by hand to prepare your script, document.querySelector
and similar functions might appear to work on a frame because the frame becomes active when focused in the console, but this won't be the case from the script's perspective, leading to a good deal of potential confusion.
Upvotes: 1