How to identify an element whose id is dynamically changing and has no other attributes in selenium? - 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();

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

Get preceding sibling with Xpath

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.

Checkbox id keeps changing in webpage causing selenium script to fail

I am trying to automate a click on a certain checkbox. However after every run the checkbox id changes and script fails to find the element. Is there an alternate way of writing an xpath
<span id="field_key$0993573c-83b4-30d4-9139-44e44b496d0f$1food_contamination-checkbox" class="v-checkbox v-widget" ca-help-field-id="undefined">
<input id="gwt-uid-193" type="checkbox" value="on" tabindex="0" checked=""/>
<label for="gwt-uid-193"/>
</span>
xpath I used was this:
//*[#id='gwt-uid-193']
If the parent <span> id is fixed you can use it and go one level down to the checkbox
driver.findElement(By.cssSelector("#field_key$0993573c-83b4-30d4-9139-44e44b496d0f$1food_contamination-checkbox > input"));
Or use the parent class
driver.findElement(By.cssSelector(".checkbox > input"));
And if you have only one checkbox you can use the type attribute
driver.findElement(By.cssSelector("[type='checkbox']"));
I found a solution myself. We can use xpath based on the position of the checkbox, i.e.:
// input[#type='checkbox'])[position()=3]
This can be used for radio buttons as well. Replace checkbox with radio.

Robot & Selenium Tree Element Expansion

My supervisor has recently switched us from HP-UFT to Robot with the Selenium Webdriver and I'm finding it extremely difficult to figure out how to use the driver and/or keyword framework to expand a folding tree ul/li webelement.
Below is a stripped out example of the code on the page:
<ul>
<li class="node-class open" id="i1454430045821320">
<a class="" style="" href="">
<ins> </ins>Location Header 1</a>
<ul>
<li class="node-instance leaf" id="i1454430058247421">
<a class="" style="" href="">
<ins> </ins>Location 1</a>
</li>
<li class="node-instance last leaf" id="i14545337159411690">
<a class="" style="" href="">
<ins> </ins>Location 2</a>
</li>
</ul>
</li>
<li class="node-class closed " id="i14544407827351156">
<a class="" style="" href="">
<ins> </ins>Location Header 2</a>
</li>
What I'm trying to do should be extremely simple: I want to expand a specifed closed tree structure if it's classed as closed. Beneath each branch is an optional nested branch, or a selection checkbox. My end goal is to be able to drill down to a location in the tree that the tester specifies and click the end leaf.
Using "Click Element|xpath=/ul/li[a[contains(text(),'Location Header 2')]" does expand the branch but it also selects all of the child node checkboxes.
In UFT, if I hit this kind of problem I'd simply change the parent <li> class to force it open (if I couldn't click or use any of the other methods to drill down and select).
In Robot, I can use the keyword "Get Element Attribute" to READ the class, but I don't see a keyword to CHANGE it so that idea is out. What I'm looking for is a way to expand the tree branches without inadvertently selecting all of the child nodes.
The drilling down through the tree portion I can deal with once I figure out how to open the nodes correctly but opening up the branch without potentially selecting all of the sub-items is making me pound my head into my desk.
I keep thinking that maybe I'm missing something simple. Any assistance on something that I could try would be greatly appreciated.
Figured it out! Thank you all so much for the ideas.
Click Element At Coordinates | xpath=//ul/li[a[contains(text(),'Location Header 2')] | -100 | 0
Luckily all of the ul element columns on the page have the same css style which sets them at 200px width. I figured through trial and error that the "At Coordinates" option clicks from the center of the object (and not the top left as I originally thought). I figured I'd share this in case anyone else ever has a similar problem.

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.