Puppeteer Login Selector: no node found? - node.js

I want to click on a login button on a website when I'm trying to login however its giving me an error of no node found for a selector
input=[name="Log In"]
and this is how the website login looks liike
<input type="submit" value="Log In" class="buttonss" style="font-size:19px">
How can i select this input in puppeteer?
this is what I have
await Promise.all([
page.click('input[name="Log In"]'),
page.waitForNavigation({ waitUntil: "networkidle0" }),
]);

There is no "name" prop on that input. Try:
'input[value="Log In"]'

Related

Reset Password Page Not Rendering Correctly When Accessing from Reset Email Link

Ok, so first off, this is my first post. I've searched high and low for a solution, but have found none. I have posted this first on Udemy, for the course I've taken, but no one has answered, so I'm reposting it here.
I have been trying very hard to figure out why the new-password page will not display correctly for me. The reset link works fine, and I can even reset the password on my new password page when I am sent there from the email link.
However, no matter what I do, I can't get it to display any styling. It only gives me basic html. The logic works fine, it's just the page that doesn't display correctly.
I know it isn't a path issue to the css folder either. If I simply render as another basic page without any token logic, such as replacing my index page with the new-password page, then it displays normally. I just don't know what I'm missing, or if there was some updates that I need to take into consideration.
I'm hoping someone sees this and can help me out. It's the only thing that doesn't work right, and it's very frustrating.
Just to be a little more clear, if I do something like below, and just replace or create a route, the page shows up correctly. It's the token logic I believe that is breaking the rendering, I just don't know how, since I don't get any errors.
Please let me know what code you may need to see, as I'm not sure what sections would be helpful, there are a lot of moving parts here. I will be happy to post whatever is needed.
exports.getNewPassword = (req, res, next) => {
res.render("auth/new-password", {
path: "/new-password",
pageTitle: "Update Password",
});
};
With the logic built-in and following the email reset link, the below will not render any styling, only the html.
exports.getNewPassword = (req, res) => {
const token = req.params.token;
User.findOne({
resetToken: token,
resetTokenExpiration: { $gt: Date.now() },
})
.then((user) => {
if (!user) {
req.flash(
"error",
"That reset password link has already been used."
);
return res.redirect("/");
}
let message = req.flash("error");
message.length > 0 ? (message = message[0]) : (message = null);
res.render("auth/new-password", {
path: "/new-password",
pageTitle: "New Password",
errorMessage: message,
userId: user._id.toString(),
passwordToken: token,
});
})
.catch((err) => console.log(err));
};
I am using ejs for templating as well. As I said above, if I remove all token logic and just render the page as a normal view, it works fine.
<main>
<% if (errorMessage) { %>
<div class="user-message user-message--error"><%= errorMessage %></div>
<% } %>
<form class="login-form" action="/new-password" method="POST">
<div class="form-control">
<label for="password">Password</label>
<input type="password" name="password" id="password">
</div>
<input type="hidden" name="userId" value="<%= userId %>">
<input type="hidden" name="passwordToken" value="<%= passwordToken %>">
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
<button class="btn" type="submit">Update Password</button>
</form>
</main>
Well, in case anyone stumbles across this, the answer was pretty simple, though I'm not sure why in this one instance is was a problem. However, the solution was to add a forward slash in front of my path to the css location for the update password page.
Again, not sure why it needed it, seeing as all my other css and view pages were in the same folder structures and worked fine, but it apparently solved the issue. SMDH.
<link rel="stylesheet" href="/css/login.css" />

Clicking a button which is hiding within a link tag in Pupeteer

Hi Pupeteer community,
I'm struggling with a simple test automation to click an "Accept All" Banner shown on the bottom of a page. The button, unfortunately, is not of type button, but wrapped within an link tag. It is hidden in the following code:
<a _tagc1="" class="accept-all mat-button mat-button-base mat-raised-button" mat-button="" aria-label="Some label" tabindex="0" aria-disabled="false">
<span class="mat-button-wrapper">
<div _tagc1="" class="action-wrapper-notice">
<strong _tagc1="">Some Button Text</strong>
</div>
</span>
<div class="mat-button-ripple mat-ripple" matripple=""></div>
<div class="mat-button-focus-overlay"></div>
</a>
I tried to click it with Puppeteer like this:
async function run () {
const browser = await puppeteer.launch({headless : false});
const page = await browser.newPage();
await page.goto(url, {waitUntil:'networkidle2'});
await page.screenshot({path: 'screenshot1.png'});
await page.click('a.accept-all.mat-button.mat-button-base.mat-raised-button', {waitUntil:'networkidle2'})
await page.screenshot({path: 'screenshot2.png'});
browser.close();
}
.. but cant get the button pressed.
Does anyone know how to best select the button? The only thing I did and seems to work is sending repeatedly Keyboard Tabs to the page and then submitting an Enter key. But I am looking at a more robust and elegant solution.
Thanks for helping a Puppeteer newbie!

How to handle focus with puppeteer on Html tags that don't have id, problem with multiple and hidden classes

I am trying to automate login and scrape for some data, html tags on the web page doesn't have ID only classes. For some reason first time I can focus on input and enter my email address but with similar code it won't type password and I can't figure out why?
I have tried
await page.waitForSelector('.login__form-wrap > .form > div:nth-child(1) > .form-group > .form-control')
await page.click('.login__form-wrap > .form > div:nth-child(1) > .form-group > .form-control')
await page.keyboard.type('myemailaddress', {delay: 100});
and it's working for email. Then similar code for password not working:
await page.waitForSelector('.login__form-wrap > .form > div:nth-child(2) > .form-group > .form-control');
await page.click('.login__form-wrap > .form > div:nth-child(2) > .form-group > .form-control');
await page.keyboard.type('mypassword', {delay: 100});
Also tried this way:
await page.waitForSelector('input[name=email]');
await page.focus('input[name=email]');
await page.keyboard.type('myemailaddress', {delay: 100});
again working, but doing the same for password:
await page.waitForSelector('input[name=password]');
await page.focus('input[name=password]');
await page.keyboard.type('myemail', {delay: 100});
doesn't work...
Doesn't work means that the password is not typed in input field.
Another solution I tried was:
await page.$eval('input[name=password]', el => el.value = "mypassword");
That works(the pass was shown), but clicking on login button it said wrong password, and when I typed it manually the same password is correct and page logs me in.
So if someone can point me in right direction of doing it, or how to handle it and show me what I'm doing wrong I would be so thankful.
P.s if you want to play with it the page I'm trying to log in is here
I already passed the validation and full code is here

With Puppeteer how can I click the parent element of my selector?

The markup i have to work with looks like this:
<label>
<input type="radio" name="myfield" value="Yes" size>
</label>
I want to call page.click(selector) with the radio as the selector, but I can't. I don't think it is visible because of the size attribute.
My javascript looks like this:
const page = await browser.newPage();
const selector = 'input[name="myfield"]';
await page.click(selector);
So I would like to target and click the parent label element.
How do I change the value of my selector constant to target the label?
Sorry, I didn't explain very well. By can't, i mean that the element is not visible and therefore i don't believe it can technically be clicked. Therefore I think i need to target the label which is visible, but i don't know how I target it
not visible or not visible at the moment?
Have you tried to use waitForSelector(selector) ?
const page = await browser.newPage();
const selector = 'input[name="myfield"]';
await page.waitForSelector(selector); // waiting here before click
await page.click(selector);
Or something like:
const page = await browser.newPage();
const selector = 'label';
await page.waitForSelector(selector);
await page.evaluate((_) => {
document.querySelector('label > input[name="myfield"]').parentElement.click()
});

Cannot find a way to tap() this element (wd,nodejs)

I have a DOM like this:
<form id="frmResendPassword" role="form" method="post">
<div class="form-group">...</div>
<span class="pull-right">
<button type="submit" class="btn btn-sm btn-default">
Resend Password</button>
</span>
</form>
I want to tap the "Resend Password" button.
I have tried many different selectors such as:
elementByClassName("btn-default")
elementById("frmResendPassword")
elementByName("Resend Password")
elementByCss(thecsspath)
ect.... none of them perform the tap()...
however they do not throw a element not found error....
so im confused. can some one please help
update:
Here is the basic automation code... its very basic
it("should send text to phone", function(){
sleep.sleep(5)
return browser
.elementByName("mobileNo")
.sendKeys(usrnme)
.elementByCss("#frmResendPassword button[type=submit]")
.tap()
})
It types the mobile number in fine, however it seems to just ignore pressing the button.
My guess is that the selector is the problem. Try this:
elementByCss("button[type=submit]")
or if that doesn't uniquely identify it, maybe this:
elementByCss("#frmResendPassword button[type=submit]")
In English that means a button with type value of submit that has an ancestor of a form where the id(#) is frmResendPassword
This is how I solved it, thanks to mrfreester
it("should send text to phone", function(){
sleep.sleep(5)
return browser
.elementByName("mobileNo")
.sendKeys(usrnme)
.elementByCss("#frmResendPassword button[type=submit]")
.click()
})

Resources