Break Dojo Query after first match - dojo

I am using
var tab = dojo.query("[widgetid^='pvr_widget_TabContainer'][0]",toolbar.domNode.parentNode)[0];
and the reason i want first element only is some of the childs are like
pvr_widget_TabContainer_0_button1 etc which holds true for my condition,
so I dont want to traverse them , can I just break the query after getting first element ?

You can use CSS selector "first-of-type" with inside the dojo.query .
Would look like this:
var tab = dojo.query("[widgetid^='pvr_widget_TabContainer']:first-of-type");
I Have a JSFIDDLE prepared for you:
http://jsfiddle.net/anmos5r8/

Related

Click on first element contained in a div

I have a div that contains a set of dynamic elements. I want to click on the first search result.
I want to click on the first element contains in
I tried using creating a custom xPath like so but it didn't work. Any ideas here?
//div[1][contains(text(), 'listing')]
First of all It would've helped if you had provided more information.
best will be using pseudo-child like div.firstChild or if the elements are generated dynamically you can add a class and use document.querySelectorAll(".class") which will give you an array of elements that had the class.
You can use array[0] to use click on the first element.
For anyone coming across this thread here is the solution
const listings = await page.$x('//*[contains(#id,"listing_")]')

Selenium finding elements returns incorrect elements

I'm using Selenium to try and get some elements on a web page but I'm having trouble getting the ones I want. I'm getting some, but they're not the ones I want.
So what I have on my page are five divs that look like this:
<div class="membershipDetails">
Inside each one is something like this:
<div class="membershipDetail">
<h3>
VIP Membership
</h3>
</div>
They DO all have this same link, but they don't have the same text ('VIP Membership' would be replaced by something else)
So the first thing was to get all the divs above in a list. This is the line I use:
listElementsMembership = driver.find_elements_by_css_selector(div[class^='membershipDetail'])
This gives me five elements, just as I would expect. I checked the 'class' attribute name and they are what I would expect. At this point I should say that they aren't all EXACTLY the same name 'membershipDetail'. Some have variations. But I can see that I have all five.
The next thing is to go through these elements and try and get that element which contains the href ('VIP Membership').
So I did that like this:
for elem in listElementsMembership:
elemDetailsLink = elem.find_element_by_xpath('//a[contains(#href,"EditMembership")]')
Now this does return something, but it always got me the element from the FIRST of the five elements. It's as if the 'elem.find_element_by_xpath' line is going up a level first before finding these hrefs. I kind of confirmed this by switching this to a 'find_elements_by_xpath' (plural) and getting, you guessed it, five elements.
So is this line:
elemDetailsLink = elem.find_element_by_xpath('//a[contains(#href,"EditMembership")]')
going up a level before getting its results? If it is, now can I make it not do that and just restrict itself to the children?
If you are trying to find element with in an element use a . in the xpath like below:
listElementsMembership = driver.find_elements_by_css_selector(div[class^='membershipDetail'])
for elem in listElementsMembership:
elemDetailsLink = elem.find_element_by_xpath('.//a') # Finds the "a" tag with respect to "elem"
Suppose if you are looking for VIP Membership:
listElementsMembership = driver.find_elements_by_css_selector(div[class^='membershipDetail'])
for elem in listElementsMembership:
value = elem.find_element_by_xpath('.//a').get_attribute("innerText")
if "VIP Membership" in value:
print(elem.find_element_by_xpath('.//a').get_attribute("innerText"))
And if you dont want iterate over all the five elements try to use xpath like below: (As per the HTML you have shared)
//div[#class='membershipDetail']//a[text()='VIP Membership']
Or
//div[#class='membershipDetail']//a[contains(text(),'VIP Membership')]
You've few mistake in that css selector.
Quotes are missing.
^ is for starts-with, not sure if you really need that. In case it's partial matching please use * instead of ^
Also, I do not see any logic for the below statement in your code attempt.
The next thing is to go through these elements and try and get that
element which contains the href ('VIP Membership').
Code :
listElementsMembership = driver.find_elements_by_css_selector("div[class*='membershipDetail']")
for ele in listElementsMembership:
e = ele.find_element(By.XPATH, ".//descendant::a")
if "VIP Membership" in e.get_attribute('href'):
print(e.text, e.get_attribute('href'))
You can give an index using a square bracket like this.
elemDetailsLink = elem.find_element_by_xpath('(//a[contains(#href,"EditMembership")])[1]')
If you are trying to get an element using XPath, the index should start with 1, not 0.

clicking on dynamic values in a web table in selenium

Below is my Table structure:
I want to click on the first cell of "policyno " column only if value is not empty
How do I achieve this?
Since you didn't specified, I have no idea what programming language do you need, but the idea is the same for all. I've used C# for the code below:
Get all the policy number elements. This can be easily achieved by getting the elements by xpath. In your case, I expect the lblPolicyNumber to be present in all:
IList allPolicyElems = driver.FindElements(By.Xpath(".//*[contains(#id,'lblPolicyElements')]"));
Now, you have 2 options to click on the element you need. First, you click on an element using his position in the list: allPolicyElems[0].Click(); (not the best way to do it) or by using LINQ (or lambda expressions for Java) to get the element by the text (perhaps you have the text stored in a variable from some previous actions): allPolicyElems.FirstOrDefault(t => t.Text == "your_text_here").Click();
This can be further expanded by applying the same logic in case you need to get the correct element by knowing other cell values from the same row.
Try using this.
WebElement elem = driver.findElement(By.xpath("//table/tbody/tr[2]/td[3]/span/a"));
if(!(elem.getText().trim().equals(""))){
elem.click();
}

fetching element from 2nd element of array protractor

I have 4 container boxes on a page which are identical. I have taken all of them in an array. Now each container box contains some elements which are identical as well. I want to fetch 2nd element from 1st container.
Below is what i used to fetch my container and it is working fine:
var pageContent = element(by.css('[class="main-content"]'));
expect(pageContent.all(by.css('.modularBoxContent')).count()).tobe(4);
Now if i want to fetch count of all elements with class as labelText insider modular box container, i am able to do that by using below:
expect(pageContent.all(by.css('.modularBoxContent')).all(by.css('[class="labelText"]')).count()).tobe(10);
But this is giving me labelText present in all 4 containers. I want to get count of labelText only in first container or get text of first labelText in first container. I tried below code but it is not working and getting error message
TypeError: this.pageContent.get is not a function
expect(pageContent.get(0).all(by.css('.modularBoxContent')).all(by.css('[class="labelText"]')).count()).tobe(3);
I also tried below but that is not working as well.
Getting same error as above for this as well.
expect(pageContent.all(by.css('.modularBoxContent')).get(1).all(by.css('[class="labelText"]')).get(0).getText()).tobe(3);
Can someone please suggest correct usage?
I think this should work for you, let's try this. Since all containers have the same class, create an array with .all() and use .get() to retrieve the desired index.
var pageContent = element(by.css('.main-content'));
var firstContainer = pageContent.all(by.css('.modularBoxContent')).first(); // or could have used .get(0);
Once your first container is successfully identified, now you just chain locator calls to find all the children under it. Since you said you wanted the second element under the first container, we'll use .get(1) (1 is the index, so it's the second item in the array).
var secondChild = firstContainer.all(by.css('[class="labelText"]')).get(1);
And, just an FYI, a lot of this could probably be refactored to be shorter if you wanted. For example, you can chain your CSS calls, no need to separate them:
The above code should be the same as this:
var firstContainer = element.all(by.css('.main-content .modularBoxContent')).first();
var secondChild = firstContainer.all(by.css('.labelText')).get(1);

Robotframework selecting an element by index

Basically I am searching for a syntax that I can use to select an element that shares the same name, properties and attributes.
I was thinking of selecting them via Index. (Unfortunately Xpath wont work since it's a dynamic element.)
So, I have a page where the element Add is shown twice, both of them adds/throws a different value. But both of them has the same ID, Attributes and Name. In my test I need to select the first Add and then the other.
${add attributes row} //*[#data-bind="click: function() {
$parents[1].addItem($parents[1]
.attributes()[$parentContext.$index()]) }", index=1]
${add attributes row_2} //*[#data-bind="click: function() {
$parents[1].addItem($parents[1]
.attributes()[$parentContext.$index()]) }", index=2]
Is there a way to select them by Index?
If you find an XPath that selects both of them, you can apply a predicate to the entire XPath by putting the XPath in parentheses. For instance, //a selects all anchors throughout the DOM. (//a)[4] selects the 4th anchor found in the DOM. You can also use the last and position functions to select relative indices such as the penultimate anchor (//a)[last()-1]
Try a locator like this for the 1st:
xpath=(//*[#data-bind="click: function() {$parents[1].addItem($parents[1].attributes()[$parentContext.$index()]) }"])[1]
Try a locator like this for the 2nd:
xpath=(//*[#data-bind="click: function() {$parents[1].addItem($parents[1].attributes()[$parentContext.$index()]) }"])[2]
See this related question