Selenium inside siblings - selenium

Is there a way to click further inside siblings in Selenium Webdriver? For example, here's the HTML:
<tr class="rich-table-row xx-datalist-even" onmouseover="Element.addClassName(this, 'xx-datalist-mouseover')" onmouseout="Element.removeClassName(this, 'xx-datalist-mouseover')">
<td class="rich-table-cell xx-datalist " id="userTableForm01:usersTableData:264:j_id102" style="text-align:center; width:20px;">
<img src="/static/images/graphics/status1.gif" title="Disabled" />
</td>
<td id="userTableForm01:usersTableData:264:col1" class="rich-table-cell xx-datalist">
<span id="userTableForm01:usersTableData:264:author_id">2377</span>
</td>
<td id="userTableForm01:usersTableData:264:col2" class="rich-table-cell xx-datalist">seleniumtest2312</td>
<td id="userTableForm01:usersTableData:264:col3" class="rich-table-cell xx-datalist">
<span style="margin-right:3px">Test2312</span>
Selenium
</td>
<td class="rich-table-cell xx-datalist " id="userTableForm01:usersTableData:264:col4" style="text-align:center;">
<input type="checkbox" name="userTableForm01:usersTableData:264:j_id111" onclick="A4J.AJAX.Submit('userTableForm01',event,{'similarityGroupingId':'userTableForm01:usersTableData:264:j_id112','parameters':{'userTableForm01:usersTableData:264:j_id112':'userTableForm01:usersTableData:264:j_id112'} } )" />
</td>
<td id="userTableForm01:usersTableData:264:col6" class="rich-table-cell xx-datalist">
<a id="userTableForm01:usersTableData:264:enable_link" href="#" style="margin-right:5px" onclick="if(typeof jsfcljs == 'function'){jsfcljs(document.getElementById('userTableForm01'),{'userTableForm01:usersTableData:264:enable_link':'userTableForm01:usersTableData:264:enable_link'},'');}return false">
<span id="userTableForm01:usersTableData:264:enable_link_text" class="xx-datalist">Enable</span>
</a>
<a id="userTableForm01:usersTableData:264:edit_link" href="#" style="margin-right:5px" onclick="if(typeof jsfcljs == 'function'){jsfcljs(document.getElementById('userTableForm01'),{'userTableForm01:usersTableData:264:edit_link':'userTableForm01:usersTableData:264:edit_link'},'');}return false">
<span id="userTableForm01:usersTableData:264:edit_link_text" class="xx-datalist">Edit</span>
</a>
<a id="userTableForm01:usersTableData:264:remove_link" href="#" onclick="if(typeof jsfcljs == 'function'){jsfcljs(document.getElementById('userTableForm01'),{'userTableForm01:usersTableData:264:remove_link':'userTableForm01:usersTableData:264:remove_link'},'');}return false">
<span id="userTableForm01:usersTableData:264:remove_link_text" class="xx-datalist">Delete</span>
</a>
</td>
</tr>
Now, this is a much bigger table than shown, so there are a lot more tr's with more users. The ID's are all auto-generated and different each time, and I am trying to click the 'Enable'-link, though the only thing unique on the same row that I can use is the username seleniumtest2312, which has brought me to this:
driver.findElement(By.xpath("//td[text()='seleniumtest2312']/following-sibling::td[3]/span[text()='Enable']")).click();
But it just won't work (no such element).
If there are better ways of solving this issue I'll be happy to try them.

The last part of your XPath is a bit off :
following-sibling::td[3]/span[text()='Enable']
because <span> you're looking for isn't direct child of <td>. You can try this XPath instead :
//td[.='seleniumtest2312']/following-sibling::td[3]/a/span[.='Enable']

Related

Vue clickable row and href conflict

Sorry. An upside-down question. I have this table. That is clickable through iWasClicked function, but I also have the last td with clickable images (href). I want the last td to be only clickable through the images(href). Now, it triggers both. The href link and the iWasClicked from the tr.
<tr
class="bg-gray-100 text-dark text-center cursor-pointer hover:bg-gray-300"
v-for="currentView in getOrganizationsDashboard().projects"
:key="currentView.id"
#click="iWasClicked(currentView.projectName)"
>
<td class="px-4 py-3 border-b-2 border-dark">
<!-- {{ showProjectSuccessRunPercentage(currentView)}} -->
<img
class="w-10 inline-block align-middle"
:src="showProjectSuccessRunPercentage(currentView)"
alt="Organization Icon"
/>
</td>
<td class="px-4 py-3 border-b-2 border-dark">
{{ currentView["projectName"] }}
</td>
<td class="px-4 py-3 border-b-2 border-dark">
<a
class=" "
:href="
'https://xxx.us/org/' + currentView['projectName']
"
target="_blank"
><img
class="inline-block w-10"
alt=""
src="../assets/img/myLogo.svg"
/></a>
</td>
</tr>
You have to stop the click event from bubbling up and triggering a click on the tr, which you can do like this:
<a #click="$event.stopPropagation()"</a>
<a
class=" "
:href="'https://xxx.us/org/' + currentView['projectName']"
target="_blank"
#click.stop
>
<img class="inline-block w-10"
alt=""
src="../assets/img/myLogo.svg"/>
</a>
It is much better to use the provided Vue event modifiers for #click which is .stop. Like what Brother Woodrow answered, this will also stop the click event's propagation.
<tr #click.stop="iWasClicked(currentView.projectName)">

Dynamically added HTML element after click event

I don't know how to add dynamic content in my Vue js 2 app. I'd like to add many div elements after clicking on a button. THis div should have input and after clicking on a Save button all input texts inside dynamically created divs should be sent to backend (so I use model inside my template).
<div v-if="!this.spinnerVisibleForCorrectiveActions">
<div>
<table class="p-2 table-cell">
<tr class="font-weight-bold">
<td class="vue-good-table-col-200">
<div class="mt-2 criterion">
ID
</div>
</td>
<td class="vue-good-table-col-200">
<div class="mt-2 criterion">
DZIAŁANIE
</div>
</td>
<td class="vue-good-table-col-200">
<div class="mt-2">
SZCZEGÓŁY
</div>
</td>
</tr>
<tr v-for="(actions,index) in correctiveActions" :key="index">
<td class="vue-good-table-col-200">
<span> {{actions.orderNumber}}</span>
</td>
<td class="vue-good-table-col-200">
<span> {{actions.action}}</span>
</td>
<td class="vue-good-table-col-200">
<span> {{actions.recommendations}}</span>
</td>
</tr>
</table>
<button class="addAction p-3 mb-2 bg-secondary text-white w-100 bg-info btn btn-success">NAdd new action</button>
<br>
</div>
How to add dynamically (multiple times) something like this and additionally to have the possibility to get all data from my dynamically created inputs after clicking on a button:
<tr v-for="(actions,index) in correctiveActions" :key="index">
<td class="vue-good-table-col-200">
<span> {{actions.orderNumber}}</span>
</td>
<td class="vue-good-table-col-200">
<span> {{actions.action}}</span>
</td>
<td class="vue-good-table-col-200">
<span> {{actions.recommendations}}</span>
</td>
</tr>
Ok, the answer in my case is very simple - I have to only add an empty object to my correctiveActions array:
<button class="addAction p-2 mb-2 bg-secondary text-white w-100 bg-info btn btn-success" #click="addNewAction">Nowe
działanie
</button>
and next:
methods:{
addNewAction() {
this.correctiveActions.push
({
id: undefined,
incidentId: this.incidentId,
orderNumber: this.getNextOrderNumber(),
action: undefined,
recommendations: undefined
});
},
}

RobotFramework : How to retrieve the row of an array corresponding to a cell value

In the UI I'm working with, for an object there there is a pencil or a basket icon; I want to click the pencil one (which will trigger an edit modal), and want to do it for the specific object.
For now I use this command line:
Click Element xpath = (//a[#ng-click="openCreateEditModal (holding)"])[2]
I would like to replace the "2" by the value of the line corresponding to the value "RF-Account".
Here is a sample of the HTML:
<tbody ng-if="!isEmpty" class="body-table ng-scope" style="height: 165px;">
<!-- ngRepeat: tenant in tenants track by $index --><tr ng-repeat="tenant in tenants track by $index" class="ng-scope" style="">
<td class="ng-binding">RF-Accou</td>
<td>
<span class="text-bold ng-binding text-muted" ng-class="{'text-green' : tenant.status == 'ACTIVE', 'text-muted' : tenant.status == 'INACTIVE'}">INACTIVE</span>
</td>
<td style="width:118px">
<div class="pull-right">
<a name="editBtn" type="submit" class="btn-icon" ng-click="openCreateEditModal(tenant)">
<span class="icon-i-edit fs" data-toggle="tooltip" title=""></span>
</a>
<a name="deleteBtn" type="submit" class="btn-icon" ng-click="deleteTenant(tenant)">
<span class="icon-i-trash fs" data-toggle="tooltip" title=""></span>
</a>
</div>
</td>
</tr><!-- end ngRepeat: tenant in tenants track by $index --><tr ng-repeat="tenant in tenants track by $index" class="ng-scope">
**<td class="ng-binding">RF-Account</td>**
<td>
<span class="text-bold ng-binding text-muted" ng-class="{'text-green' : tenant.status == 'ACTIVE', 'text-muted' : tenant.status == 'INACTIVE'}">INACTIVE</span>
</td>
<td style="width:118px">
<div class="pull-right">
<a name="editBtn" type="submit" class="btn-icon" ng-click="openCreateEditModal(tenant)">
<span class="icon-i-edit fs" data-toggle="tooltip" title=""></span>
</a>
<a name="deleteBtn" type="submit" class="btn-icon" ng-click="deleteTenant(tenant)">
<span class="icon-i-trash fs" data-toggle="tooltip" title=""></span>
</a>
</div>
</td>
</tr><!-- end ngRepeat: tenant in tenants track by $index --><tr ng-repeat="tenant in tenants track by $index" class="ng-scope">
<td class="ng-binding">RF-Accountfirst</td>
<td>
<span class="text-bold ng-binding text-muted" ng-class="{'text-green' : tenant.status == 'ACTIVE', 'text-muted' : tenant.status == 'INACTIVE'}">INACTIVE</span>
</td>
<td style="width:118px">
<div class="pull-right">
<a name="editBtn" type="submit" class="btn-icon" ng-click="openCreateEditModal(tenant)">
<span class="icon-i-edit fs" data-toggle="tooltip" title=""></span>
</a>
<a name="deleteBtn" type="submit" class="btn-icon" ng-click="deleteTenant(tenant)">
<span class="icon-i-trash fs" data-toggle="tooltip" title=""></span>
</a>
</div>
</td>
</tr><!-- end ngRepeat: tenant in tenants track by $index -->
</tbody>
I am trying to find the line that corresponds to the text value "RF-Account".
For your information, the line of "RF-Account" can change.
Could you please help me find the right keyword to use for Robot Framework ?
To rephrase your question - you need a locator that'll get you that, not a robotframework keyword (the keyword is known, Click Element).
If your anchor is the text, then this xpath will do it for you:
//td[text()="RF-Account"]/following-sibling::td//a[#ng-click="openCreateEditModal(tenant)"]
Let me explain: the first part (//td[text()="RF-Account"]) will select a td element which text is "RF-Account". Then it will look for a follow-up td (the "following-sibling axis), that has an a child with that value for ng-click - and return it (the a).
BTW, in the sample source there is no "openCreateEditModal(holding)", thus I've changed it with "tenant", which is present.
For getting count you can use
Get Matching XPath Count //td[.="RF-Account"]

Not able to check the check box, exception "element not visible"

In an table which can contain more rows, user is searchable using the email id. After searching, selecting the first check box. But selenium is throwing the element not visible exception.
//*[#id='share_user']/tbody/tr1/td1//label
//*[#id='share_user']/tbody/tr1/td1//input
//label[#for='checkbox_416']
last identifier is dynamic. Still getting the element not visible exception.
Table code is mentioned below
<table class="table table-striped table-hover dataTable" id="share_user"
aria-describedby="share_user_info">
<thead>
<tr role="row">
<th class="small-cell sorting" role="columnheader" tabindex="0"
aria-controls="share_user" rowspan="1" colspan="1" style="width: 137px;"
aria-label="Share Profile : activate to sort column ascending">Share Profile </th>
<th class="medium-cell sorting" role="columnheader" tabindex="0"
aria-controls="share_user" rowspan="1" colspan="1" style="width: 523px;"
aria-label="User Details: activate to sort column ascending">User Details</th>
<th class="medium-cell sorting_asc" role="columnheader" tabindex="0"
aria-controls="share_user" rowspan="1" colspan="1" style="width: 366px;"
aria-sort="ascending" aria-label="Access: activate to sort column descending">Access</th>
</tr>
</thead>
<tbody role="alert" aria-live="polite" aria-relevant="all">
<tr class="odd">
<td class="">
<div class="checkbox check-default">
<input name="checkUser" id="checkbox_416" value="416" class="shareCheck"
type="checkbox">
<label for="checkbox_416"></label>
</div>
</td>
<td class=" ">
<img src="" class="img-responsive display-inline share-image">
<div class="display-inline">
<p class="share-name">alexx</p>
<p class="muted">
<i class="fa fa-envelope" hidden="true"></i>
<span>alexxm360#gmail.com</span>
</p>
</div>
</td>
<td style="vertical-align: middle;" class=" sorting_1">
<div class="select2-container medium-cell" id="s2id_rolelink416"
style="float:left;">
<a href="javascript:void(0)" onclick="return false;" class="select2-choice"
tabindex="-1">
<span class="select2-chosen">PROFILE ADMIN</span>
<abbr class="select2-search-choice-close"></abbr>
<span class="select2-arrow">
<b></b>
</span>
</a>
<input class="select2-focusser select2-offscreen" id="s2id_autogen11"
type="text">
<div class="select2-drop select2-display-none select2-with-searchbox">
<div class="select2-search">
<input autocomplete="off" autocorrect="off"
autocapitalize="off" spellcheck="false" class="select2-input"
type="text">
</div>
<ul class="select2-results">
</ul>
</div>
</div>
<select name="profileUsers.roleId" id="rolelink416"
class="medium-cell select2-offscreen" style="float:left;" tabindex="-1">
<option value="6">PROFILE ADMIN</option>
<option value="7">PROFILE AGENT</option>
<option value="8">PROFILE VIEWER</option>
<option value="196">profile role</option>
</select>
</td>
</tr>
</tbody>
</table>
providing the screen shots as well.
Try to use explicit wait with Expected Conditions
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement checkbox = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#id='share_user']/tbody/tr[1]/td[1]//input")));
checkbox.click();
You can use the following expression, I have verified working fine.
driver.findElement(By.xpath("//*[#id='share_user']/tbody/tr[1]/td[1]/div")).click();
Try this
int ele_size=driver.findElements(By.xpath("locator")).size();
driver.findElements(By.xpath("locator")).get(ele_size-1).click();
We might encounter element not visible exception if element matching the locator existed in the DOM but is not currently visible. So we have to take the size of the element in first statement then in next statement we have to take the first element from the list and click on element.
Used this //*[#id='share_user']/tbody/tr[1]/td[1]/div worked

How to get xpath for this element

I have lot of tr tag with same structure in my page . The only way to select "Google" is by starting the XPATH from "ImgTrash.png" . Please let me know if you have idea .
<tr>
<td width="1%"/>
<td class="Fol" nowrap="" style="padding-left: 0px">
<a id="A57" href="3745474">
<img src="ImgTrash.png"/>
<span style="vertical-align:middle">Trash </span>
</a>
</td>
</tr>
<tr class="Row">
<td width="1%"/>
<td class="Fol" nowrap="" style="padding-left: 8px">
<a id="A56" href="507023">
<img src="ImgFolder.png"/>
<span style="vertical-align:middle">Google </span>
</a>
</td>
</tr>
You will need an XPath like this:
//a[img/#src = 'ImgFolder.png']/span
Breakdown:
//a searches for all <a> elements
[img/#src = 'ImgFolder.png'] only selects the <a> elements that have a child <img> with the attribute src. This attribute src should exactly match (case-sensitive) ImgFolder.png
/span at the end will get the child <span> from the previous selected <a>