Puppeteer how to click the child element of 'next sibling' - css-selectors

I want to select and click the specified <a> of next sibling, html code
below:
<ul>
<li>
<a></a>
</li>
<li>
<a></a>
</li>
<li class='abc'>
<a></a>
</li>
<li>
<a></a> <!-- I want to click this link -->
</li>
</ul>
the <ul> is changing, but the <li class='abc'> is changeless
and use the code below:
let tag = await page.evaluate(() => {
return document.querySelector('li.abc').nextSibling.a
})
console.log(tag?'Y': 'N')
// await page.click(tag)
then it output 'N'
Can someone help me fix this error?
Thanks in advance!

Got this answer from Dave Batiste(user of puppeteer.slack.com),
Thanks to #Vaviloff point that: I should post this answer.
Use the code page.click('.abc + li > a') can click the specified <a> that I want to,
and Dave Batiste(user of puppeteer.slack.com) give more info as below:
If you do want a handle that you can call methods on, I think you'd be interested in > page.$...
const handle = await page.$(selector);
handle.click(options);

Related

How to get length by children collactions with Cypress?

I use Cypress.io with ReactJs
i have the html structure
<ul class="wrapper">
<li class="class-1">1</li>
<li class="class-2">2</li>
<li class="class-3">3</li>
<li class="class-4">4</li>
<li class="class-5">5</li>
</ul>
How can i get length of li elems?
like this document.querySelector(.wrapper > li).length
cy.get('.wrapp > li').length does not work
Like it is said in Cypress docs
cy.get('.wrapper li') // this yields us a jquery object
.its('length')
.then(length =>{
//code that uses the length
})
You can use something like:
cy.get('.wrapper').find('li').its('length').then((len) => {
//Do stuff with length
expect(len).to.equal(5)
})

How do I compare with css class in ng-click?

I'm trying to prevent ng-click action if css class is empty or not equal until class="visited" that allows ng-click action
Here is my code
<ul class="nav nav-wizard">
<li>
Step 1
</li>
<li>
Step 2
</li>
<li>
Step 3
</li>
<li>
Step 4
</li>
<li>
Step 5
</li>
</ul>
These shouldn't be executed by click until css class is showed like this.
<li class="visited">
Step 1
</li>
This is able to do click if it meets class="visited" condition.
<a ng-click="doSomething($event.currentTarget.getAttribute('class'))">Hello, click me</a>
// In controller:
$scope.doSomething = function(classes) {
if(classes && classes.indexOf("visited") > -1){
//do click properly
}else{
//do nothing
}
};
https://jsfiddle.net/rpuczu4a/
This is probably something you don't want to do as AngularJS philosophy is to focus on model manipulation and let AngularJS do the rendering (based on hints from the declarative UI). Manipulating DOM elements and attributes from a controller is a big no-no in AngularJS world.
You can make it work like so using the pointer-events css attribute (The jQuery is just demonstration Javascript):
$('a[ng-click]').click(function(event) { event.preventDefault(); this.innerHTML = "YAY"; });
a[ng-click] {
pointer-events:none;
}
a[ng-click].visited {
pointer-events:all;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Test(DISALLOW CLICK) <br />
Test (ALLOW CLICK)

ng-repeat - content to show if array is empty or null

I've a deep nested ng-repeat lists, and only in the last loop I've to display alternate content if list was empty. I'm new to angular, saw some posts online please help me where can I use content if list is empty. The ng-repeat=sessions in day could be empty.
<ul class="day">
<li ng-repeat="sessions in day">
<ul class="table-view">
<li class="table-view-cell" ng-repeat="(heading, session) in sessions">
<span class="group">{{heading}}</span>
<ul class="cell">
<li class="cell-content" ng-repeat="val in session" ng-click="getSession(val.id)">
<div class="time" style="background-color:#{{val.color}}">
<span>{{val.start | date:"h:mma"}}</span>
<span>to</span>
<span>{{val.end | date:"h:mma"}}</span>
</div>
<div class="session" ng-class-odd="'odd'" ng-class-even="'even'">
<span class="name">{{val.name}}</span>
<span class="room">Room: {{val.room}}</span>
</div>
</li>
</ul>
</li>
</ul>
</li>
</ul>
1). CSS approach. I usually use pure CSS approach in such cases. With this markup (stripped extra-html):
<ul class="day">
<li ng-repeat="sessions in day">
...
</li>
<li class="no-sessions">
No sessions on this day.
</li>
</ul>
and CSS rules to hide .no-sessions li by default and make it visible only if there are no previous li tags:
li.no-sessions {
display: block;
}
li + li.no-sessions {
display: none;
}
So when sessions array is empty, there will be no li rendered and only no-sessions one will be visible. And if will hide as soon as there is at least one session on this day.
Demo: http://plnkr.co/edit/KqM9hfgTTiPlkdmEevDv?p=preview
2). ngIf approach. Of course you can use ngIf/ngShow directives for show no-records element when sessions array is empty:
<li ng-if="!day.length">
No sessions on this day.
</li>
I think this would work for your case:
<li ng-hide="day.length > 0">
No sessions on this day.
</li>
No extra CSS needed. Assumes day is an array.
http://plnkr.co/edit/WgDviOKjHKS1Vt5A5qrW
I would recommend handling that in your controller. Keeping your logic in the controller and javasript makes debugging easier and more manageable. I can think of 2 approaches: using ng-show/ng-hide or a condition for your day variable when its empty.
Option 1
ng-show/ng-hide approach:
$scope.isDayEmpty = function(){
return $scope.day.length > 0 ? false : true;
}
html:
<ul class="day">
<li ng-repeat="sessions in day" ng-hide="isDayEmpty">
...
</li>
<li ng-show="isDayEmpty">
No Sessions this Day
</li>
</ul>
Option 2:
ng-repeat approach
if($scope.day.length == 0){
$scope.day.push("No Sessions this Day");
}
This should get you essentially the same result. The first approach would make your CSS styling easier assuming you want to do something different in that case.
The second approach can vary in style depending on your code but thats an example of how you can do it. I don't know your javascript so I can't be more specific to your scenario.

How to select by class or id using selenium Webdriver?

i'm using Java/Selenium-webdriver/Eclipse
i want to click on an element which is in a menu of a webapp.
So i have to click on Menu and it shows a list and then i clik on an item.
i try to select the item "Chaine" with linkText and sometimes it's working
When i select with xpath it's working but i think it's not safe.
So i want to select by id or class.
How can i select "Chaine" by Id or class.
Or what is the best way to select this item.
THank you
So the html code is here:
<ul class="list">
<li class="component-panel-item" data-component="bar-graph">
<a>
Bar graph
</a>
</li>
<li class="component-panel-item" data-component="line-graph-ch">
<a>
Chaine
</a>
</li>
<li class="component-panel-item" data-component="line-graph-en">
<a>
En Graph
</a>
</li>
You can try out below code.
IWebElement ul = ie.FindElement(By.ClassName("list"));
ul.Click();
foreach (IWebElement li in ul.FindElements(By.ClassName("component-panel-item")))
{
if (li.Text.Equals("Chaine"))
{
li.Click();
}
}

jQuery live sibling-selector not working

I have this CSS selector, which just won't bind .live(), but works perfectly with .bind():
$('.treeView li ~ :has("ul")').prev('li')
I've read somewhere, that using the .prev() and .next() could be troublesome coupled with .live(), so I wanted to create an pure CSS selector (or ANYTHING that works with .live()!) to do the job - but I just can't figure it out!
Here's what I want to do:
Select all li-elements, which is followed by an li containing an ul.
Here's an HTML markup example, I want to select the ones where the comment says "selected"
<div class="treeView" id="processSegmentsTree">
<ul>
<li>Ostetanke</li> //selected
<li>
<ul>
<li>Tank 1</li>
<li>Tank 2</li>
</ul>
</li>
<li>Presse</li> //selected
<li>
<ul>
<li>Sub-leaf 1</li>
<li>Sub-leaf 2</li> //selected
<li>
<ul>
<li>test</li>
<li>test</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
Any help is much appreciated, since this is a bit of a thorn in my eye :(
There is no such Selector to accomplish this task.
What I highly recommend you to do is to add ANYTHING as a flag to use when selecting your desired elements.
add attribute, wrapper, ANYTHING YOU WANT, then the task will be as easy as it should be.
This may work: // not css selector
$(".treeView li:has('ul')").prev();

Resources