Selenium Element - selenium

Not able to select a dynamic drop down PFB the html tag of the element.
Drop down dynamic ids:
page:frm:pageB:repeatUpper:0:repeat:1:ServiceSubtype
page:frm:pageB:repeatUpper:0:repeat:2:ServiceSubtype
HTML Code :
<td class="dataCell" style="border-top:1px solid #838282;">
<span id="page:frm:pageB:repeatUpper:0:repeat:1:DescPopup" class="DescServicePopupClone" style="display:none;"></span>
<span id="page:frm:pageB:repeatUpper:0:repeat:1:DescPopupHasResource" class="DescServicePopupHasResource" style="display:none;"></span>
<span id="page:frm:pageB:repeatUpper:0:repeat:1:DescPopupLOE" class="DescServicePopupLOE" style="display:none;"></span>
My code:
new Select(driver.findElement(By.xpath("//td[contains(#id, 'page:frm:pageB:repeatUpper:0:repeat:')]"))).selectByVisibleText("CAT-New Implementer");
Thread.sleep(18000);
getting the below error:
Caused by: org.openqa.selenium.NoSuchElementException: Unable to
locate element: {"method":"xpath","selector":"//td[contains(#id,
'page:frm:pageB:repeatUpper:0:repeat:')]"} For documentation on this
error, please visit:
http://seleniumhq.org/exceptions/no_such_element.html
UPDATE from OP - part of the "real" HTML:
<select id="page:frm:pageB:repeatUpper:0:repeat:2:ServiceSubtype" name="page:frm:pageB:repeatUpper:0:repeat:2:ServiceSubtype">
<option value="">--None--</option>
<option value="CAT-New Implementer">CAT-New Implementer</option>
<option value="CAT-Repeat Implementer">CAT-Repeat Implementer</option> </select> </span> </td>

Try this one:
new Select(driver.findElement(By.xpath("//select[starts-with(#id, 'page:frm:pageB:repeatUpper:0:repeat:')]"))).selectByVisibleText("CAT-New Implementer");
I also changed "contains" to "starts-with" because that better suits your example.

My suggestion to you is to not use XPath. Prefer ID, then maybe name, and then CSS Selectors. Those 3 locators should be 99% of your find methods. XPath is complex, fragile, and slow. Stick to the simple things until you get them mastered and then move on to XPath when you absolutely must.
This code should work
Select dropdown = new Select(driver.findElement(By.id("page:frm:pageB:repeatUpper:0:repeat:2:ServiceSubtype")));
dropdown.selectByVisibleText("CAT-New Implementer");
Since you have an ID on the SELECT, use that. Because it is a SELECT, casting the WebElement to a Select gets you extra options only available for SELECTs as far as choosing OPTIONs. For your example, you can use either .selectByVisibleText() or .selectByValue() since they are equivalent in the HTML you provided.
EDIT 1
Another option is to look for a partial ID, ID ends with ($) X, but I don't know if that is unique on your page.
Select dropdown = new Select(driver.findElement(By.cssSelector("span[id$=':ServiceSubtype']")));
Yet another option is to increment a counter and insert that into your ID string.
int i = 0;
Select dropdown2 = new Select(driver.findElement(By.id("page:frm:pageB:repeatUpper:0:repeat:" + i + ":ServiceSubtype")));
// i++; each time you add something

Related

Selenium XPATH selecting next sibling

<div class="block wbc">
<span></span>
<span> text_value </span>
</div>
for getting text in second span where does below code go wrong?
driver.find_element(X_PATH,"*//div[#class='block']/span[1]")
For trying by yourself, maybe I write sth wrong here is link
https://soundcloud.com/daydoseofhouse/snt-whats-wrong/s-jmbaiBDyQ0d?si=233b2f843a2c4a7c8afd6b9161369717&utm_source=clipboard&utm_medium=text&utm_campaign=social_sharing
And my code; still giving an error
playbackTimeline__duration =driver.find_element(By.XPATH,"*//div[#class='playbackTimeline__duration']/span[2]")
For finding web element clearly:
//*[#id="app"]/div[4]/section/div/div[3]/div[3]/div/div[3]/span[2]
But I will not use this way, I need declare with class method or CSS Selector at least
If you are sure that you always need the second span use this XPath:
*//div[#class='playbackTimeline__duration']/span[2]
If you need the first span that has actual text use this:
*//div[#class='playbackTimeline__duration']/span[normalize-space()][1]
If the #class has more than only playbackTimeline__duration in it you can use:
*//div[contains(#class,'playbackTimeline__duration')]/span[2]
If there are more div's like that use:
*//div[contains(#class,'playbackTimeline__duration')][1]/span[2]

How to find an item in Selenium WebDriver?

I want to find the following item using Selenium. The value of the class changes whenever there is a change. This is inside a complex page (multiple iframes, and other items loaded dynamically). The only unique id is itemid, which is dynamic value and title combination. If I click on this Action, am getting another new set of complex items. I am new to Selenium. How to do that?
HTML:
<td itemid="xxyyy.as123" title="Actions" nowrap="" class="text-button">Actions <img src="../row.gif"></td>
<td itemid="xxyyy.as123" title="Actions" nowrap="" class="text-button button-active">Actions <img src="../row.gif"></td>
<td itemid="xxyyy.as123" title="Actions" nowrap="" class="text-button button-hover">Actions <img src="../row.gif"></td>
The code I tried:
Find by Xpath
var element=driver.FindElement(By.XPath("html/body/div[id='pageContent']/iframe/#document/ht‌ml/frameset/frame[name='detailsDisplay']/#document/html/body/form[name='tableForm‌']/div[id='divToolbarContainer']/div[id='divToolbar']/div[1][class='toolbar']/tab‌​le/tbody/tr/td[title='Actions']"));
Find by Link Text
var element = driver.FindElement(By.LinkText("Actions"));
Any help would be appreciated.
Try
By.CssSelector("td[title="Actions"]");
By.CssSelector("td[itemid="xxyyy.as123"]");
By.CssSelector("td[itemid="xxyyy.as123"][title="Actions"]")
Create Dynamic CSS Selector.
For Example:
driver.FindElement(By.CssSelector("td[itemid$="xxyyy."]")).Click();
Note: In dynamic Elements, there is always a part of locator wich is fixed. we need to generate the locator using this part.
If fixed part is at starting - Use Carrot Character (^)
If fixed part is at Middle - Use Asterisk sign (*)
If fixed part is at End - Use Doller sign ($)
Finally I was able to achieve it, by using the frame names.
driver.SwitchTo().Frame("content").SwitchTo().Frame("detailsDisplay");
var element = driver.FindElement(By.XPath("//*[#id=\"divToolbar\"]/div[1]/table/tbody/tr/td[1]"));
Thanks everyone.

Xpath for checkboxes without IDs

What xpath can I use for something like this without using ID? Or if there are more checkboxes but IDs are still different after refreshing page?
<td class="player" style="vertical-align: top;">
<span class="gb-CheckBox">
<input id="gb-uid-120" type="checkbox" value="on" tabindex="0" style="background-color: rgb(255, 255, 255);">
<label for="gb-uid-120"></label>
</span>
</td>
Try following:
//span[#class="gb-CheckBox"]/input[#type="checkbox"]
Why not:
//input[#type='checkbox']
this should be enough and will select all inputs that are checkbox type.
If you need only from a certain area then you need to add a constraint by adding another selector in front of this like:
//div[#class='my_prefered_area']//input[#type='checkbox']
Another way of getting the selector would be to use the pare of the id that does not change like:
//input[contains(#id, 'gb-uid')]
Of course you can also add the restriction for checkbox type:
//input[contains(#id, 'gb-uid')][#type='checkbox']
Seems like you got the answer as most of the ways mentioned above are correct.
Correcting the first one path wit CSS :
td.player>span.gb-CheckBox>input[type='checkbox']
(try it removing the spaces before and after > )
Or
td.player>span.gb-CheckBox>input
Will also work.
As you mentioned, if your Id is changing frequently, that means its an dynamic webelement and
if it is changing at the end(after gb-uid- i.e. gb-uid-120, then gb-uid-121 something like this) then use contains function on Xpath as below:
//span[#class="gb-CheckBox"]/input[contains(#id, 'gb-uid-')]
You can also locate this checkbox easily using cssSelector instead of xpath which would be much faster as below :-
td.player > span.gb-CheckBox > input[type='checkbox']

Clicking on checkbox based on span value in WebDriver

I Would like to select the the checkbox based on "Costco Wholesale Corporation" value in:
<td role="gridcell" style="" title="" aria-describedby="entity-search-grid_selected">
<input type="checkbox" name="chkbox" class="itmchk" value="110504">
</td>
<td role="gridcell" style="font-weight: bold;" title="Costco Wholesale Corporation" aria-describedby="entity-search-grid_name">
<div class="tree-wrap tree-wrap-ltr" style="width:18px;">
<div style="left:0px;" class="ui-icon ui-icon-triangle-1-s tree-minus treeclick"></div>
</div>
<span class="cell-wrapper">Costco Wholesale Corporation</span>
</td>
I have tried the following code:
driver.findElement(By.xpath("//td[span[text()='Costco Wholesale Corporation']]/preceding-sibling::td/input[#name='chkbox'"));
but getting following exception:
invalid selector: Unable to locate an element with the xpath expression //td[span[text()='Costco Wholesale Corporation']]/preceding-sibling::td/input[#name='chkbox' because of the following error: SyntaxError: Failed to execute 'evaluate' on 'Document': The string '//td[span[text()='Costco Wholesale Corporation']]/preceding-sibling::td/input[#name='chkbox''
Could you help to write the xpath selector.
Your first problem is that xpath td[span[text() is definitely invalid. Remember that the [...] syntax is only for filters, not for defining the path. So it has to be:
//td/span[text...
Also since you select span first, you need to get back to td level and then choose a sibling:
//td/span[text()='Costco Wholesale Corporation']/../preceding-sibling::td/input[#name='chkbox']
Given your HTML, you could also simplify it to select td byt title and then its sibling:
//td[#title='Costco Wholesale Corporation']/preceding-sibling::td/input[#name='chkbox']
I wonder why you want to use xpath. The moment someone changes the structure of the site the whole selector will be worthless. I really recommend sticking to css selectors as long as you can. In this case it's just:
driver.findElement(By.css("input[name='chkbox'][value='110504']"));
And the main advantage of this approach is that only changes which directly concern the element will force you to change the selector.
Of course my selector might not be valid if there are some parts of site that you didn't show us and that may have inpact on selector. But even then I believe there is a way to use css to get to the element more directly.
Your provided xPath is syntactically incorrect.. try using below xPath :-
String xPath = "//span[text()='Costco Wholesale Corporation']/preceding::input[#name='chkbox']";
driver.findElement(By.xpath(xPath));
Hope it helps...:)

xpath in selenium for clicking the element

This is the HTML code, for the box, please advice me on how to find the correct xpath for any element in this box.
The box contains list of elements and the element is transferred from left to right box or vice versa when clicked.
<div id="companyIndustry" class="form-group" style="margin:0">
<select id="my-select-industry" name="segmentdiv:companyIndustries" multiple="multiple" size="8">
<option value="1">Agriculture and Mining - Farming and Ranching</option>
<option value="2">Agriculture and Mining - Fishing, Hunting and Trapping</option>
</select>
</div>
Xpath can be:-
//select[#id='my-select-industry']/option[#value='2']
In this case you can use
Select dropdown = new Select(driver.findElement(By.id("my-select-industry")));
To select its option say 'Agriculture and Mining - Fishing, Hunting and Trapping' you can do
dropdown.selectByVisibleText("Agriculture and Mining - Fishing, Hunting and Trapping ");
or
dropdown.selectByIndex(2);
or
dropdown.selectByValue("2");
Hope it will help you :)
List<WebElement> options = driver.findElements(By.xpath("//option"));
You could also search for 'option' tags with relative xpath (searching downward from a 'known' [previously found] element), but that would require you to add a '.' dot instead of double slash before 'option'.
e.g.
WebElement selectElement = driver.findElement(By.id("my-select-industry"));
List<WebElement> options = selectElement.findElements(By.xpath("./option"));
There's a similar example of what you're trying to do here: http://forum.testproject.io/index.php?topic=19.0