Clicking a button which is hiding within a link tag in Pupeteer - node.js

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!

Related

Puppeteer Login Selector: no node found?

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"]'

puppeteer show result in screenshot but cant get value of that result

after click on the search button, the puppeteer take a screenshot but I can't get the element's value
here is my code
await page.$eval('#textInputSelector',(el, licenceInfo) =>
(el.value = licenceInfo),licenceInfo)
const searchBtn = await page.$x('//*[#id="searchBtnXPath"]')
await searchBtn[0].click()
await page.waitFor(4000);
console.log(await page.$eval('#selector1', el => el.innerText));
await makeScreenShot(page, screenPath, { fullPage: true })
and the result is (red box)
result's image
and its HTML code output
<div>
<span id="#selector1" >
Your search returned no results. Please modify your search criteria
and try again.
</span>
</div>
and button html code
<div id="#selector2">
<a id="searchBtnXPath" href="
javascript:
__doPostBack('ctl00$PlaceHolderMain$btnNewSearch','');
var p = new ProcessLoading();p.showLoading(false);">
<span>Search</span>
</a>
</div>
and this is my error
Error: failed to find element matching selector "#selector1"
Use this instead:
console.log(await page.$eval('body #selector1', el => el.innerHTML));

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()
})

Foundation 6 reveal modal events not firing for me

I want videos playing in the reveal modal window to stop playing when the modal window closes (who doesn't?). This is easily done with jQuery by setting the iframe source to empty.
But I can't figure out how to make it work in a callback. The modal window itself functions as expected. And this works:
$('.close-button', '#video-reveal').on('click', function() {
$('#video-player').attr("src", "");
console.log("button event fired");
});
However, neither of the following has any effect:
// from documentation
$(document).on('close.fndtn.reveal', '[data-reveal]', function() {
var modal = $(this);
console.log("closing reveal event fired");
});
// my attempt to do it programmatically
$('[data-reveal]').on ('opened.fndtn.reveal', function() {
var modal = jQuery(this);
console.log("opened reveal");
});
So it feels like the event is not firing. I'm sure it is, but how to capture it?
The magic of Foundation 6 is not all obvious without some digging. Working with version 6.2.3
$(document).on(
'open.zf.reveal', '[data-reveal]', function () {
console.log("'open.zf.Reveal' fired.");
}
);
It appears as though you are using Foundation 5's callbacks, rather than Foundation 6...
For your callbacks, I'd suggest using 'closed.zf.reveal', 'open.zf.reveal' or 'closeme.zf.reveal' as mentioned here:
http://foundation.zurb.com/sites/docs/reveal.html
In HTML
<!--the button -->
<a class="button" data-open="videoModal" href="#">Example Video Modal</a>
<!--Modal Video -->
<div class="row" id="theVideo">
<div id="videoModal" class="reveal" data-reveal data-close-on-click="true">
<h2>This modal has video</h2>
<div class="flex-video">
<iframe id="youtubePlayer" width="854" height="480" src="https://www.youtube.com/embed/4z6aSO05YHg" frameborder="0" allowfullscreen allowscriptaccess="always"></iframe>
</div>
<button class="close-button" data-close aria-label="Close reveal" type="button" onClick="destroyVideo()">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
<!--in apps.js-->
function destroyVideo(){
var url = $('#youtubePlayer').attr('src');
$('#youtubePlayer').attr('src', '');
$('#youtubePlayer').attr('src', url);
}

Ionic nav-back-button and menu button showing together

I try to make the menu button not to show when the back button is showing. is there a way to let Ionic take care of that? or it's up to me?
for example if i use ui-sref to go from app.users to app.users.add or app.users.details i expect the menu button to be hidden and the back button to show, but they're both showing when i go to nested views. example:
<button class="button button-positive" ui-sref="app.users.details({id:user.id})"> User details </button>
app.js
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'templates/menu.html'
//controller: 'AppCtrl'
})
.state('app.users', {
url: '/users',
views: {
'menuContent#app' : {
controller: 'UsersCtrl',
templateUrl: 'templates/users.html'
}
}
})
.state('app.users.add', {
url: '/addUsers',
views: {
'menuContent#app' : {
controller: 'AddUserCtrl',
templateUrl: 'templates/add_user.html'
}
}
})
.state('app.users.details', {
url: '/userDetails/:id',
views: {
'menuContent#app' : {
controller: 'UserDetailsCtrl',
templateUrl: 'templates/details_user.html'
}
}
})
}
menu.html
<ion-side-menus>
<ion-pane ion-side-menu-content>
<ion-nav-bar class="bar-stable">
<ion-nav-back-button class="button-clear">
<i class="icon ion-ios7-arrow-forward"></i> back
</ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view name="menuContent" animation="slide-right-left"></ion-nav-view>
</ion-pane>
<ion-side-menu side="right">
<header class="bar bar-header bar-stable">
<h1 class="title">Title</h1>
</header>
<ion-content class="has-header">
<ion-list>
<ion-item nav-clear menu-close ui-sref="app.users">
Users
</ion-item>
<ion-item nav-clear menu-close ui-sref="app.users.add">
New user
</ion-item>
</ion-list>
</ion-content>
</ion-side-menu>
</ion-side-menus>
My views structure is as such:
<ion-view title="Title">
<ion-nav-buttons side="right">
<button menu-toggle="right"class="button button-icon icon ion-navicon"></button>
</ion-nav-buttons>
<ion-content class="has-header">
...
View Content
...
</ion-content>
</ion-view>
This is done by ionic by default now in beta 14. You can also toggle this by this attribute.
<ion-side-menus enable-menu-with-back-views="false">
Relative Codepen
Sidemenu Starter Project
Sidemenu Docs
Is also possible to override that from a child page just adding the ion-side-menus directive inside the child template:
<ion-side-menus enable-menu-with-back-views="true"></ion-side-menus>
<ion-view view-title="My Child page">
<ion-content>
<h1>HEY</h1>
</ion-content>
</ion-view>
This will add the complete navigation bar (ion-nav-bar) inside your child page that was added into menu.html template (according with the example above)
Place the navbar with menu button on the html page on which you need menu button and place navbar with back button on the page where you need back button.
Like this I need Menu On home page so place your navbar on homepage with menu button
<ion-view title="home">
<ion-nav-bar class="bar-stable main-header-nav home-page">
<ion-nav-buttons side="left">
<button class="button button-icon button-clear ion-navicon" menu- toggle="left"></button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-content></ion-content>
</ion-view>
And I need back button on Inbox page so use navbar with backbutton on inbox page
<ion-view title="">
<ion-nav-bar class="bar-stable main-header-nav home-page">
<ion-nav-back-button class="button-clear go-back">
</ion-nav-back-button>
</ion-nav-bar>
<ion-content></ion-content>
</ion-view>
I solved in 2019 adding the property "menuToggle" to the Button. That tells Ionic/Angular that the function of that button is to be the "Hamburguer Button" so, Angular understand and hide it when the "Back Arrow Button" is shown.
<button menuToggle ion-button icon-only (click)="btnHamburger()">
<ion-icon name="menu"></ion-icon>
</button>

Resources