Nested predicates in Xpath - selenium

I am trying to access the div node via
//div[#data-full='2018-1-15']
Normally I would just search by Xpath and grab this node. However the nature of the site is that there are a number of nodes with this property, and only one is clickable.
Because of this I have to grab the
//div[#class='dw-cal-slide dw-cal-slide-a']
node first and then step down. I know I'm trying to do something like this:
Step down one node:
//div[#class='dw-cal-slide dw-cal-slide-a']/div/
And then search for child nodes that have a child node of their own with the property
//div[#data-full='2018-1-15'].
Having trouble with the syntax. Any help would be great!

Try
//div[contains(#class, 'dw-cal-slide') and contains(#class, 'dw-cal-slide-a')]//div[#data-full='2018-1-15']
But IMHO it's better (shorter expression) to use CSS selector
div.dw-cal-slide.dw-cal-slide-a div[data-full='2018-1-15']
If you want to locate ancestor and descendant div in two code lines, then you can use (Python example)
ancestor = driver.find_element_by_xpath("//div[contains(#class, 'dw-cal-slide') and contains(#class, 'dw-cal-slide-a')]")
and
descendant = ancestor.find_element_by_xpath(".//div[#data-full='2018-1-15']")

As you said, there are multiple node with same property and only one is clickable. you can click on the node by checking isEnable. other thing you can try with following-sibling or preceding-sibling. example can be found on below stackoverflow link:
How to use XPath preceding-sibling correctly

Related

locate displayed element with webdriverio

When developing in the Ionic framework, the generated html sometimes will contain duplicate DOM elements, where all but one tree of elements is hidden with a class="ion-page-hidden" at the top level.
When using webdriverio to try and locate an element inside this tree, it find duplicated elements. Since the ion-page-hidden class is at the top of the tree, and not on the element itself, how can we use Xpath to locate only the displayed element.
I couldn't figure out any way to modify the XPath selector with a second condition since the elements are exactly the same!
So instead I have tried to use the webdriverio isDisplayed() function:
get openHamburgerMenu() { return Utils.visibleElement($$("//ion-button[#name='button-open-menu']")); }
where the Utils function is:
async visibleElement(elementArray) {
let returnElement;
elementArray.forEach(element => {
if (element.isDisplayed()) {
returnElement = element;
}
});
return returnElement;
}
but no elements are passed into the function. In the chrome browser, I can see two that match the xpath //ion-button[#name='button-open-menu']. I need the one not in the ion-page-hidden block!
tree
The tree looks like this:
app-for-homes[1]/ion-header/ion-toolbar/ion-buttons[1]/ion-button
app-for-homes[2]/ion-header/ion-toolbar/ion-buttons[1]/ion-button
where app-for-homes[2] happens to have the ion-page-hidden class.
I think it should be possible to use ancestors to identify which of the two elements, matching the xpath, does not have a 4th level ancestor with that class? But I'm way out of my depth on day one of working with xpaths...
Quick and Dirty
The desired outcome can be achieved using this Xpath:
//app-for-homes[1]/ion-header/ion-toolbar/ion-buttons/ion-button[#name='button-open-menu']
However, this only works where the order in which the elements appears is known.
Better Answer
When you have exactly 1 element that is not hidden, Xpaths allow you to look at an elements ancestors as far back as you want to identify the presence / or absence of the hidden class. In this case, we start by finding the ancestor app-for-homes which does not include the ion-page-hidden class:
//app-for-homes[not(contains(#class,'ion-page-hidden'))]
and then simply append the remainder of the path to the desired element. Full answer =
//app-for-homes[not(contains(#class,'ion-page-hidden'))]/ion-header/ion-toolbar/ion-buttons/ion-button[#name='button-open-menu']

Can we use Condition with axes in XPATH?

Can we use Condition with axes in XPATH?
Trying to check both parent and child in XPath. Example:
//span[text()='Accounts']/parent::a OR child::div
I know this is wrong. But is there any way to check the condition?
I know the situation looks vague. But I am trying to find a logic where I can use both parent and child axes to create an XPath.
The main motive is to inspect an element from UI and create XPath using axes. and automate the process.
When I am trying the above XPath, it throws some error.
Maybe if you use | instead of OR
//span[text()='Accounts']/(parent::a|child::div)

what is the difference between "//div[.//a[text()='SELENIUM']]" and "//div[//a[text()='SELENIUM']]" in selenium xpath

what is the difference between "//div[.//a[text()='SELENIUM']]" and "//div[//a[text()='SELENIUM']]" in selenium xpath.
Can some one please clarify my query on xpath, what is the difference when i give dot(.) before //a and without dot(.) .//a
you can use the above mentioned xpath's in this url "http://demo.guru99.com/selenium/guru99home/" to see the difference.
//x searches the whole tree
.//x searches the subtree under the context node
So in a predicate, //div[//x] selects a div if there is an x anywhere in the document, while //div[.//x] selects a div if there is an x within the subtree rooted at that div.

how to select the check box using selenium?

How to select the checkbox which has a dynamically changing ID and XPath?
Multiple ways:
You should look at a pattern like id or name somoething like
CT_CHKBox_157, CT_CHK_158 etc.. For example, to click the first
Checkbox having a pattern of Ids
You can use a dynamic xpath like driver.findelement(By.xpath(//input[starts-with(#id,'CT_CHK'][1]).click()
Identify the Unique Element which are close ancestors to the
Checkbox in question and reach out to it through xpath or css path
relatively or through indexing from within.
Hope that clarifies.
Have you tried XPath by position? Ultimately the check boxes are like buttons or link that can be clicked so driver.findElement(By.xpath("//xpath by position")).click();
Alternativey you might want to use JavaScript:
((JavascriptExecutor) driver).executeScript("return document.getElementsByName('ChkboxValue')[0].checked;");
Hope this helps.
Selenium uses what is called locators to find and match the elements.There are 8 locators strategies included in Selenium:
Identifier
Id
Name
Link
DOM
XPath
CSS
UI-element
you can try using any other Locator in the list.

Select an nth matched node from a list of matching nodes

I'm working with selenium to perform some automation and I'm attempting to interact with my webpage using Selenium & CSS selectors.
My question is how do I select the nth matched node returned from a list of all matching nodes?
For example my CSS selector is ".contactName" which returns 2 matching nodes. Using Selenium I want to do something like
selenium.Click("css=.contactName the second match");
Any help is greatly appreciated.
This is what I ended up using in order to select the second input with the class name
selenium.Click("xpath=(//input[#class='contactName'])[2]");
Do these two nodes share the same parent? If so, you can try one of these, depending on where they are under their parent in the DOM and whether there are any other kinds of elements:
selenium.Click("css=.contactName:nth-child(2)");
selenium.Click("css=.contactName + .contactName");
selenium.Click("css=.contactName ~ .contactName");
If these two nodes don't share the same parent, you'll probably have to go with an XPath locator instead of CSS:
selenium.Click("xpath=//*[#class='contactName'][2]");