Clicking on checkbox based on span value in WebDriver - selenium

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...:)

Related

how to find xpath of the input box in the following HTML

I have a html like this
<td class="random">
<div id="randomID">Product:</div>
</td>
<td class="random">
<div id="randomID">
<input type="text" class="random">
</div>
</td>
my xpath //div[contains(text(),"Product:")] gives me the first element for which I want to send input. How do I get the input xpath so I can do input.sendkeys() on it.
You use either of the xpath to get the input tag.
Use following and index of input tag
//div[contains(text(),"Product:")]/following::input[1]
Or find the td tag and then use following-sibling
//td[.//div[contains(text(),"Product:")]]/following-sibling::td[1]//input
You can use below xpath as well.
//div[text()="Product:"]/following::input[1]
Or
//td[.//div[text()="Product:"]]/following-sibling::td[1]//input
Use following-sibling
Try with following xpath:
//td[contains(.,"Product:")]//following-sibling::td//input
For the provided code, the input is very simple to identify:
//input[#class='random']
Since I can't see any other duplicate code to force you to be more precise, I don't see the problem in using this one.
If you have multiple , and each or some of them have an input inside, in this case:
//div[text()="Product:"]/following::input[1]
Where Product is the visible text of the div that you want to use as a parent, and then you go straight in the first input taken by its index.

Unable to find correct Target selector to click an element

Please see the image below which shows code of the web page in Developer Tools window and advise me the correct selector for 'Depreciation Models'. Text highlighted in red is constant, however the surrounding text is dynamic. So I tried using contains selector to locate but unsuccessful. I want to avoid XPATH as number of before and after div elements may keep changing.
I am using Selenium IDE hence the C#/Java code for RC/Webdriver won't help much.
Selenium IDE generated target path is this:
css=#dhxId_rgWATog7lC3E_27572|6059|6152 > td.sub_item_text > div.sub_item_text
I tried
css=contains('27572') > td.sub_item_text > div.sub_item_text
but it didn't work.
Kindly suggest. I am stuck. Thanks.
As you tried the Locator Strategy as :
css=contains('27572') > td.sub_item_text > div.sub_item_text
Reasons for not working
From the snapshot of the HTML you have provided, 27572 is not the innerText but partial string of the id attribute.
As per selenium.common.exceptions.InvalidSelectorException with “span:contains('string')”:
The :contains pseudo-class isn't in the CSS Spec and is not supported by either Firefox or Chrome (even outside WebDriver).
Solution
You can use the following xpath as per the existing DOM Tree:
xpath=//tr[#class='sub_item'][contains(#id,'27572')]//td[#class='sub_item_text']/div[#class='sub_item_text'][contains(.,'Depreciations Models')]
I guess this would be the right approach:
<style>
[id*="27572"] > td.sub_item_text > div.sub_item_text{
color:red;
}
<table>
<tbody>
<tr id="dhxId_rgWATog7lC3E_27572|6059|6152" class="sub_item">
<td class="sub_item_icon">
<i class="fa fa-user epc-down-circled-2"></i>
</td>
<td class="sub_item_text">
<div class="sub_item_text"> Depriciations Models</div>
</td>
</tr>
</tbody>
</table>
It will set all elements that have an id attribute value containing "27572" and inside of it.

Splinter Is it possible to use browser.fill without name as a query

I would like to use an absolute xpath to fill in a search bar. The ids and classes are dynamically generated and there is no name variable or instance. So it feels like I'm stuck without a tool to fill in boxes without the named variable.
Is there a way around this? Can I somehow change the absolute xpath to look like its a name assignment and then query and fill based on the new 'type' I assigned the absolute xpath?
Is there a method for this in Selenium if not available in Splinter?
I've select by CSS and I'm finding this error 'selenium.common.exceptions.InvalidElementStateException: Message: Element is not currently interactable and may not be manipulated'
Edit:
<div class="type-ahead-input-container" role="search">
<div class="type-ahead-input-wrapper">
<div class="type-ahead-input">
<label class="visually-hidden" for="a11y-ember10393">
Search
</label>
<!---->
<input id="a11y-ember10393" class="ember-text-field ember-view" aria-
autocomplete="list" autocomplete="off" spellcheck="false"
placeholder="Search" autocorrect="off" autocapitalize="off" role="combobox"
aria-expanded="true" aria-owns="ember11064" data-artdeco-is-focused="true"/>
<div class="type-ahead-input-icons">
<!---->
</div>
</div>
<!---->
</div>
</div>
As you have asked Is there a method for this in Selenium, the Answer is Yes.
Selenium supports Sikuli. Sikuli automates anything you see on the screen. It uses image recognition to identify and control GUI components. It is useful when there is no easy access to a GUI's internal or source code.
You can find more about Sikuli here.
Let me know if this answers your question.
When you get an error-message like that, it could be that your search result is not what you expected. It could be that you are getting more than one result, ie a list. On a list you can not input.
You can find the input boxes with an xpath, select the prefered one from the list (by trying) and put a text in it with the WebDriverElement _set_value method. That is not appropriate because of the _, but it is usefull.
input_list = browser.find_by_xpath('//div[#class="type-ahead-input"]/input[#class="ember-textfield ember-view"]')
input_list[1]._set_value('just a text to see whether it is working')

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

how to create xpath for the following check box

I am finding it hard to create a relative xpath for a check box . I have attached the code snippet below. Firebug gives me an absolute xpath as:
html/body/div[6]/div[2]/form/table[1]/tbody/tr[3]/td[1]/input[1].
But the form changes if there is separate entry and then absolute xpath changes to:
html/body/div[6]/div[2]/form/table[1]/tbody/tr[4]/td[1]/input[1]
(or tr[5] or any number). I tried to use the relative xpath but the firebug shows the xpath in red colour (so it is invalid)-
.//*[#id='responderSelection'155939'1']
Please help.
<form id="pollGroupForm" method="post" action="/consoleapp/newSurvey.jspx">
<div class="filter"/>
<table class="dataTable">
<tbody>
<tr>
<tr class="alternateRow">
<tr>
<td>
<input id="responderSelection'155939'1" type="checkbox" value="true" name="responderSelection['155939']"/>
<input type="hidden" value="on" name="_responderSelection['155939']"/>
</td>
<td>twoway_2</td>
<td> 26161 </td>
<td>
</tr>
</tbody>
</table>
<table>
</form>
</div>
</div>
<div id="footer">
Would you try a partial search using cssSelector? I assume the numbers with the id is dynamic so the following cssSelector let's you find the checkbox with the partial match of the id(^ means starts with)
[id^='responderSelection']
If you really want xpath then contains() is the equivalence to the css above
//input[contains(#id,'responderSelection')]
There are several different ways to do this, depending on the exact conditions.
If there is only on checkbox in that table, then you can focus on that: //table//input[#type='checkbox'].
Possibly safer selector would be to look for a checkbox in your form, as that has a fixed id attribute: //form[#id='pollGroupForm']//input[#type='checkbox']. If you can, always start from fixed ids.
If you want to get the Xpath of an element which ID is changing dynamically, there is a little trick: simply inspect the element with Firebug, delete its ID by double clicking on it (delete the whole id parameter, or change the value to "")and you will get the correct Xpath.
For example if you have the following structure:
<div id="fix-id">
<div id="dynamic-id-1214151"></div>
</div>
You will get //*[#id="fix-id"]/div[1] instead of //*[#id="dynamic-id-1214151"].