Get preceding sibling with Xpath - selenium

I have a link that hidden the element when the page is resized, so im trying to get that element, by previous element.
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
<i class="icon icon-doc-new"></i>
<span class="hidden-sm dropdown-label">Create</span>
<span class="caret hidden-sm"></span>
</a>
To get the "normal" element i use the Xpath :
.//*[#id='main-menu']/li/a/span[contains(text(), 'Create')]
then i would like to get element <i class="icon icon-doc-new"></i>
something like this
.//*[#id='main-menu']/li/a/span[contains(text(), 'Create')]/precending-sibling::i[0] //(also tried different indexes]
Have tried a couple of other methods but with no go either.
Any tips`?

Try to use below XPath:
.//*[#id='main-menu']/li/a[span[text()="Create"]]/i

So, you actually need parent element if I'm correct and not preceding sibling.
Try with .//*[#id='main-menu']/li/a/span[contains(text(), 'Create')]/parent::a
If you want preceding sibling then try with .//*[#id='main-menu']/li/a/span[contains(text(), 'Create')]/precending-sibling::i

Try any of these below mentioned xpath
//span[#class='caret hidden-sm']/..//preceding-sibling::span[text()= 'Create']
Explanation of xpath:- Use class attribute of <span> tag and move ahead with another <span> tag along with text method using preceding-sibling keyword.
OR
//span[#class='caret hidden-sm']/..//preceding-sibling::span[#class='hidden-sm dropdown-label']
Explanation of xpath:- Use class attribute of <span> tag and move ahead with another <span> tag along with class attribute using preceding-sibling keyword.

Related

Find Xpath to an element depending on the value of another element in a table row

I'm new to Xpath so if this doesn't contain all relevant information apologies & let me know what you need to solve it.
I am trying to find an Xpath to an "expand arrow" element which expands a row in a table. The "expand arrow" element isn't unique so I would like to select it based on text contained in another element on the same row. The layout is as follows:
<td id="__table2-rows-row10-col0">
<div class="sapUiTableCellFlex">
<span id="__table2-rows-row10- treeicon" title="Expand Node" role="button">
<div id="__hbox27-__clone101">
<div id="__data70-__clone101">
<div id="__data71-__clone101">
<span id="__text47-__clone101" title="sys-admin">sys-admin</span>
I'd like to select the element with title = "Expand Node"
<span id="__table2-rows-row10- treeicon" title="Expand Node" role="button">
based on the element with title or text = "sys-admin"
<span id="__text47-__clone101" title="sys-admin">sys-admin</span>
I've played around with various options but I can't seem to get it to work. Any ideas would be much appreciated!
Thanks
To locate the element with title as Expand Node with respect to the element with title or text as sys-admin you can use either of the following Locator Strategies:
xpath and title attribute:
"//span[#title='sys-admin']//ancestor::span[#title='Expand Node']"
xpath and text() attribute:
"//span[text()='sys-admin']//ancestor::span[#title='Expand Node']"
I eventually got it to work using the following xpath:
//span[#title='sys-admin']/../../preceding-sibling::span[#title='Expand Node']

How to extract the name of the authors using an XPath expression

Given below is the snippet of HTML:
<div class="a-row a-spacing-none">
<span class="a-size-small a-color-secondary">by
</span>
<span class="a-size-small a-color-secondary">
<a class="a-link-normal a-text-normal" href="/Lowell-Fryman/e/B01M3MNJTE/ref=sr_ntt_srch_lnk_1?qid=1550228622&sr=1-1">
Lowell Fryman
</a>
and
</span>
<span class="a-size-small a-color-secondary">
<a class="a-link-normal a-text-normal" href="/Gregory-Lampshire/e/B01N7ZWT5Y/ref=sr_ntt_srch_lnk_1?qid=1550228622&sr=1-1">
Gregory Lampshire
</a>
</span>
</div>
I'm trying to obtain the name of all authors.
This is whatever test follows the word by.
I came up with the following XPath but it doesn't seem to fetch all the authors.
My XPath expression:
//div//span[text()=\"by \"]//following::span[1]//a
Can someone please tell me how to obtain the name of all the authors while somehow managing to skip any element whose text is "and"?
I'm using Selenium's find_element_by_xpath if it helps.
Try the below code.This should work.It will fetch all author.
elements=driver.find_elements_by_xpath("//a[#class='a-link-normal a-text-normal']")
for element in elements:
print(element.text)
Please let me know if this work.
Here xpath you can use to get authors:
//div[./span[normalize-space(.='by')]]//a
or
//div[./span[contains(.,'by')]]//a
Your xpath should be like this:
//span[normalize-space(.='by')]/following-sibling::span//a
you can first get text of all span elements in a list and then slice it from "by" text value
elements = [_.text() for _ in driver.find_elements_by_css_selector('div.span')]
print elements[elements.index('by'):]
To print the name of all the authors which are followed by the word by you can use either of the following solutions:
Using innerHTML:
print([author.get_attribute("innerHTML") for author in driver.find_elements_by_xpath("//span[contains(., 'by')]//following::span/a[#class='a-link-normal a-text-normal'][#href]")])
Using text:
print([author.text for author in driver.find_elements_by_xpath("//span[contains(., 'by')]//following::span/a[#class='a-link-normal a-text-normal'][#href]")])

How to identify an element whose id is dynamically changing and has no other attributes in selenium?

I've this html body for a kendo dropdown list which has only one attribute i.e. id which is dynamically changing, how do i identify this object on every page refresh accurately.
other attributes like class and tab index already are present with same values multiple times on the same page for other dropdowns-
<span role="listbox" unselectable="on" class="k-dropdown-wrap k-state-default" id="dde13a91-2bf3-4e41-af72-bee1b881a8d9" dir="ltr" readonly="false" tabindex="0" aria-disabled="false" aria-readonly="false" aria-haspopup="true" aria-expanded="false" aria-owns="48f666d8-4c3c-43a8-a4dc-8e7a9961a0ef" aria-activedescendant="ca3c4431-3ebf-46c0-9510-a64a32eae108-C.US.0000110896">
<span unselectable="on" class="k-input">
<!---->
<!---->2018 ALBERTSONS / Beverage Mixes
</span>
<span unselectable="on" class="k-select">
<span class="k-i-arrow-s k-icon"></span>
</span>
<!---->
</span>
If there is a always present value in dropdown, You can try to find this value by text or something, and then get a parent:
XPath: Get parent node from child node
Other way is to get it by xpath of structure, like: div[3]/.../span etc. It is not good as every change can fail Your test, but if You have no other options, then You might want to try this.
To click on the element with the only attribute-text as 2018 ALBERTSONS / Beverage Mixes you need to induce WebDriverWait for the element to be clickable and you can use the following solution:
(Java) xpath:
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//span[#class='k-dropdown-wrap k-state-default' and #role='listbox']//span[#class='k-input']"))).click();
I found a workaround to locate the element:
First get the xpath of the span tag inside the dropdown using it's text as below:
//text()[contains(.,'2018 ')]
since '2018 ' is common irrespective of adjacent text
Then move up to the parent tag of the dropdown to locate the dropdown frame which can be collapsed on click:
//text()[contains(.,'2018 ')]/parent::/parent::
then simply click on the element which is located.
driver.findElement(By.xpath("//text()[contains(.,'2018 ')]/parent::/parent::")).click();

Does RFT have equivalent for jQuery .next() ?

I need to make work select in RFT in case the select is done via jQuery AJAX select where the html code looks like
<select style="display: none;" id="_campus_id" name="_campus_id">
<option id="CAMPUS1" value="1">camp</option>
<option id="CAMPUS2" value="2">camp2</option>
</select>
<input aria-haspopup="true" aria-autocomplete="list" role="textbox" autocomplete="off" class="ui-autocomplete-input ui-widget ui-widget-content ui-corner-left">
<button aria-disabled="false" role="button" class="ui-button ui-widget ui-state-default ui-button-icon-only ui-corner-right ui-button-icon" title="Show All Items" tabindex="-1">
<span class="ui-button-icon-primary ui-icon ui-icon-triangle-1-s"></span><span class="ui-button-text">
</span>
<button>
I need to "go" to input box and type text then "press" {DOWN} and {ENTER}. I have this part ready but the input box doesn't have any unique id so I want to find the input box based on the select which got property ID.
It would be possible using something like getNext() but I guess it doesn't exist in RFT.
Any other idea how to make this work? In case there are more than one AJAX selects on the page?
Is it the child of a specific unique object, say, a div or a form? If so, you can use the find() method to search for the child of a specific object.
Is the string "ui-autocomplete-input ui-widget ui-widget-content ui-corner-left" unique among objects of that type? You can do a find() to get all the input boxes and then loop through them checking the properties with getProperty() until you're sure you have the right one. This can be combined with the above suggestion.
Confirmed with IBM support that RFT doen't have any equivalent to jQuery .next() method as per current version. I created a ticket for an enhancement.
You can get everything from the select box and use some regular expression to search for keywords or a full sentance in that pick that as your option.

Unable to select menu item using xpath [Validates in Xpath checker, but webdriver cannot find it]

I am trying to select a menu item...though xpath validates well in Xpath checker, it does not work from WebDriver ...can someone help?
I get Unable to locate element: {"method":"xpath","selector":"//a[contains(text(),'Start Loan Process')]"}
HMTL looks something like this
<div class="bd">
<ul class="first-of-type">
<li id="yui-gen7" class="yuimenuitem first-of-type" groupindex="0" index="0">
<li id="yui-gen8" class="yuimenuitem" groupindex="0" index="1">
<li id="yui-gen9" class="yuimenuitem" groupindex="0" index="2">
<li id="yui-gen10" class="yuimenuitem" groupindex="0" index="3">
<li id="yui-gen11" class="yuimenuitem" groupindex="0" index="4">
<a class="yuimenuitemlabel" href="#">Start Loan Process</a>
I have had very little luck with using the Text() part of the xpath. I would rather use the .Text (C#) or .getText() (java) method.
This is how i would write this in c#:
driver.FindElement(By.Xpath(".//*/a").Text.Contains("Start Loan Process");
The xpath part is of course debateable. It could also be: ".//div/li/a". You can use what you want.
On the other hand you can also try to use findElementsBy(By.classname("yuimenuitemlabel"))
Get them to list of web elements and then filter it using webelement.getText() method.