XPath for dynamic table - xpath

In the application I have to click red cross mark to delete. I have attached imageImage showing Delete icon. I need an xpath to click red cross icon.
I tried following xpath but it does not work :
//div[contains(text(),'UG_AUTOMATION')]*/i[#class='x-fa fa-icon-red fa-times-circle']
Below is the html tag
<td class="x-grid-cell x-grid-td x-grid-cell-gridcolumn-1089 x-grid-cell-first x-unselectable" style="width: 485px;" role="gridcell" tabindex="-1" data-columnid="gridcolumn-1089" xpath="1"><div unselectable="on" class="x-grid-cell-inner " style="text-align:left;">UG_AUTOMATION</div></td>
<td class="x-grid-cell x-grid-td x-grid-cell-actioncolumn-1090 x-action-col-cell x-grid-cell-last x-unselectable" data-qtip="Delete" style="width:50px;" role="gridcell" tabindex="-1" data-columnid="actioncolumn-1090" xpath="1"><div unselectable="on" class="x-grid-cell-inner x-grid-cell-inner-action-col" style="text-align:center;"><span class="btn btn-default btn-sm"><i class="x-fa fa-icon-red fa-times-circle"></i></span><div tabindex="-1" role="button" class="x-action-col-icon x-action-col-0 " data-tabindex-value="0" data-tabindex-counter="1"></div></div></td>

To select the second <td> element (from where you can choose any child you want), you can use this XPath-1.0 expression:
//td[contains(div/text(),'UG_AUTOMATION')]/following-sibling::td[div/span/i/#class='x-fa fa-icon-red fa-times-circle']/#data-qtip
The last part /#data-qtip is only there to get an output (here it is Delete). Replace it as you desire.

Assuming you're using Python, you could use the following XPath (we use following axis) :
//div[contains(text(),'UG_AUTOMATION')]/following::i[#class='x-fa fa-icon-red fa-times-circle']
Piece of code with required imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
element= WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[contains(text(),'UG_AUTOMATION')]/following::i[#class='x-fa fa-icon-red fa-times-circle']"))).click()
Alternative element to click on :
//div[contains(text(),'UG_AUTOMATION')]/following::span[#class="btn btn-default btn-sm"]
If you need to click on the div element containing the icon, you have to remove its attribute :
element= WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[contains(text(),'UG_AUTOMATION')]/following::div[1]")))
driver.execute_script("arguments[0].removeAttribute('unselectable')", element)
element.click()

Related

Unable to change drop-down selection in Ruby Watir

I am trying to select values one by one in a dropdown and having difficulty.
selenium-webdriver (4.0.3)
watir (7.0.0)
ChromeDriver 94.0.4606.81
The dropdown is md-select which on click displays a hidden div with 2 choices.
<md-select ng-if="vm.datas.length" ng-model="vm.activeData" ng-change="vm.refreshDash()" id="active-data-select" aria-label="data selector" class="ng-pristine ng-valid md-default-theme ng-empty ng-touched" tabindex="0" aria-disabled="false" role="button" aria-haspopup="listbox" aria-invalid="false" aria-labelledby="active-data-select select_value_label_8" style="" aria-owns="select_listbox_10">
<md-select-value class="md-select-value" id="select_value_label_8"><span><div class="md-text">My test data 1</div></span><span class="md-select-icon" aria-hidden="true"></span></md-select-value>
</md-select>
<div class="md-select-menu-container md-default-theme md-active md-clickable" aria-hidden="false" role="presentation" id="select_container_9" style="display: block; left: 507px; top: 8px; min-width: 336.891px; font-size: 20px;">
<md-select-menu role="presentation" class="_md md-default-theme" style="transform-origin: 152.445px 32px 0px;">
<md-content role="listbox" tabindex="-1" aria-multiselectable="false" class="_md md-default-theme" id="select_listbox_10" aria-activedescendant="select_option_14">
<!---->
<md-option ng-repeat="data in ::vm.datas | orderBy:'name' track by $index" ng-value="data" value="[object Object]" ng-class="{'selected': data.name == vm.activeData.name }" tabindex="0" class="md-default-theme selected md-focused" role="option" id="select_option_14" selected="selected" aria-selected="true"><div class="md-text">My test data 1</div></md-option>
<!---->
<md-option ng-repeat="data in ::vm.datas | orderBy:'name' track by $index" ng-value="data" value="[object Object]" ng-class="{'selected': data.name == vm.activeData.name }" tabindex="0" class="md-default-theme" role="option" id="select_option_15"><div class="md-text">My test data 2</div></md-option>
<!---->
</md-content>
</md-select-menu>
</div>
When I am trying to do the below to display the hidden div to select next value:
browser.element(id: 'active-data-select').click
I get the following error:
element located, but timed out after 30 seconds, waiting for #<Watir::HTMLElement: located: true; {:id=>"active-data-select"}> to be present
I have tried many different things, but not able to find a solution yet. Any ideas?
Thank you,
-Andrey
If you are certain that clicking select element will solve your problem
browser.element(id: 'active-data-select').fire_event :click
will perform click even if element is obscured or not even on screen
You can also try
browser.element(id: 'active-data-select').send_keys :enter
or
browser.element(id: 'active-data-select').send_keys [:down, :down, :enter]
In your html it seems like div select_container_9 is holding the select with options elements, so try
browser.div(id: "select_container_9").select_list.options.first.select
It seems like it's id is autogenerated so different locator should be used in case it works
But you should probably debug how many selects there are on page with
browser.selects.count then you can flash each select to pinpoint the one you are after with browser.selects[x].flash then count how many options are available in that select with browser.selects[1].options.count and then you can proceed with selecting the option you want with browser.selects[1].options[1].select and then improve locators

Jmeter WebDriver Sampler - How to Select an Element from a table

So I'm using Jmeter WebDriver sampler and I have a table where each row has a Delete and Edit button.
The layout of the HTML table is as follows:
<tbody id=table_id>
<tr>
<td> name </td>
<td>
<a class="some random text" href="edit.php/20" role="button>edit>edit </a>
<a class="some random text" onclick="delete20"> Delete </a>
</td>
</tr>
<tr>
<td> name2 </td>
<td>
<a class="some random text" href="edit.php/21" role="button>edit>edit </a>
<a class="some random text" onclick="delete21"> Delete </a>
</td>
</tr>
I'm unsure how to tell the webdriver to click a button based on the product name without an ID to findByElementID. I was thinking maybe I can parse through the table but I'm unsure what the steps are to take that route.
Any advice would be much appreciated!
Thank you!
Identify the product by its name, i.e. name or name2 using text() function
//td[text()=' name2 ']
Locate it's following sibling
//td[text()=' name2 ']/following-sibling::td
Locate the button which you want to click, i.e. "edit" or "delete"
//td[text()=' name2 ']/following-sibling::td/a[text()=' Delete ']
Demo:
More information:
XPath Language Reference
XPath Tutorial
Using the XPath Extractor in JMeter

2 forms - Credit Card and Checking Account - 2 identical xpaths for one checkbox - automation will not click the checkbox

here is the xpath I am using
//tr[#id = 'inputSavePaymentAccounts']/descendant::input[#type = 'checkbox' and #name = 'payAck' and #tabindex = '10'
here is how I can get it to check the checkbox
jQuery('.payAck').prop('checked', true)
here is the checking account html that is inside an iframe
<tr id="inputSavePaymentAccounts" class="savePaymentAccounts" style="display: table-row;">
<td class="addCCLabel" style="padding-top: 15px;">Save this Payment Method</td>
<td style="padding-top: 15px;">
<input class="payAck" type="checkbox" onchange="friendlyNameShow()" name="payAck" tabindex="10">
</td>
</tr>
here is the credit card html that is inside the same iframe
<tr id="inputSavePaymentAccounts" class="savePaymentAccounts" style="display: table-row;">
<td class="addCCLabel" style="padding-top: 15px;">Save this Payment Method</td>
<td style="padding-top: 15px;">
<input class="payAck" type="checkbox" onchange="friendlyNameShow()" name="payAck" tabindex="25">
</td>
</tr>
The main issue is that when i use:
jQuery('.payAck').prop('checked', true)
it checkmarks the checkbox however, at the time the checkbox is checked I am suppose to see a text box display, which is not happening with the above jquery. I was hoping the execution of xpath would solve this
see these for a more clearer picture
image of checkbox http://prnt.sc/c12b1p
image of checkbox when it is checked with text box displaying (need this to happen) http://prnt.sc/c12b7q
First of all, I would recommend you remove the inline javascript. Your primary selector in this case is a class and the class is assigned to 2 elements (at least from what I see in your example). When you check the checkbox using jQuery with the class selector, it is going to trigger all the elements that belong to that class and I don't think that is what you intend to do. Also, using click() will work, but that will cause friendlyNameShow() to be called twice and you will need to check the state of the checkbox since you are not explicitly checking/un-checking it. Try using and Id instead.

Click on deeply nested div in Watir

I am trying to click on checkbox (which represents as ) in Firefox using Watir. I have code left to me from the previous tester, and this code works in Chrome, but not Firefox.
Here is what I have.
Here is the code that leads to this div:
<div class="x-grid3-body" style="width:515px;" id="ext-gen201">
<div class="x-grid3-row x-grid3-row-first" style="width:515px;">
<table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="width:515px;">
<tbody>
<tr>
<td class="x-grid3-col x-grid3-cell x-grid3-td-0 x-grid3-cell-first " style="width: 158px;" tabindex="0">
<div class="x-grid3-cell-inner x-grid3-col-0 x-unselectable" unselectable="on">Organisation</div>
</td>
<td class="x-grid3-col x-grid3-cell x-grid3-td-1 " style="width: 298px;" tabindex="0">
<div class="x-grid3-cell-inner x-grid3-col-1 x-unselectable" unselectable="on">Catch Software</div>
</td>
<td class="x-grid3-col x-grid3-cell x-grid3-td-scopeCheckColumn x-grid3-cell-last x-grid3-check-col-td" style="width: 53px;" tabindex="0">
<div class="x-grid3-cell-inner x-grid3-col-scopeCheckColumn x-unselectable" unselectable="on">
<div class="x-grid3-check-col x-grid3-cc-scopeCheckColumn"> </div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
What I need essentially is to click on this div
<div class="x-grid3-check-col x-grid3-cc-scopeCheckColumn"> </div>
I can't attach screenshots (rating is low), but this div is the checkbox that I need to click.
This piece of code works in Chrome:
#browser.div(:class => 'x-box-inner', :index => 1).table(:class => 'x-grid3-row-table').td(:text => 'Organisation').parent.td(:index => 2)
But in Firefox I can see that Watir is just click on the whole parent div (can see selection appear in browser), not on the checkbox div.
Thank you.
First off, there is only one element in the html you've showed that has the class 'x-grid3-cc-scopeCheckColumn', so is there a reason you can't do:
#browser.td(class: 'x-grid3-cc-scopeCheckColumn').click
If not, you can simplify your element location drastically to get the td you want, since there is only one td that has the text 'Organisation', and .parent would only get the td above it, but it looks like you want the tr tag above that, so perhaps you want:
#browser.td(text: 'Organisation').parent.parent.td(index: 2)
Using an XPath worked for me in Firefox:
#browser.div(:xpath, "//*[#id='ext-gen201']/div/table/tbody/tr/td[3]/div/div").click
I was able to verify it with .flash in place of .click since your div just contains a space and there was nothing to otherwise see.

Ruby Watir, Dijit Widget, set value from "select list"

I'd like to be able to click (to see available options/list of accounts, seem to be hidden to start with) and then set a dijit widget "select_list" to a certain value.
I can find the object using
##ie.element(:css, "#accountSwitcherSelect.dijitDownArrowButton").flash
#works
but cannot use click or set with it:
##ie.element(:css, "#accountSwitcherSelect.dijitDownArrowButton").click
#no errors, but doesn't do anything
##ie.element(:css, "#accountSwitcherSelect.dijitSelectLabel").set("Account2")
#NoMethodError: undefined method `set' for <Watir::HTMLElement:0x4d6af60>
##ie.element(:css, "#accountSwitcherSelect.dijitSelectLabel").send_keys("Account3")
#NoMethodError: undefined method `send_keys' for <Watir::HTMLElement:0x4d6af60>
In the past the site was implemented using plain html and had a select_list, so
##ie.select_list(:name, "link").set(/Account1/i)
worked just fine.
Here's the current html behind the site:
<table id="accountSwitcherSelect" class="dijit dijitReset dijitInline dijitLeft dijitDownArrowButton dijitSelectFixedWidth dijitValidationTextBoxFixedWidth dijitSelect dijitValidationTextBox" lang="en-US" cellspacing="0" cellpadding="0" aria-haspopup="true" role="listbox" data-dojo-attach-point="_buttonNode,tableNode,focusNode" style="-moz-user-select: none; width: 207px;" tabindex="0" widgetid="accountSwitcherSelect" aria-expanded="false" aria-invalid="false">
<tbody role="presentation">
<tr role="presentation">
<td class="dijitReset dijitStretch dijitButtonContents" role="presentation">
<div class="dijitReset dijitInputField dijitButtonText" role="presentation" data-dojo-attach-point="containerNode,_popupStateNode" popupactive="true">
<span class="dijitReset dijitInline dijitSelectLabel dijitValidationTextBoxLabel " role="option">Account1</span>
</div>
<div class="dijitReset dijitValidationContainer">
</td>
<td class="dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer" role="presentation" data-dojo-attach-point="titleNode">
<input class="dijitReset dijitInputField dijitArrowButtonInner" type="text" role="presentation" readonly="readonly" tabindex="-1" value="? ">
</td>
Assuming that the the "select list" is similar to those on the digit.form.Select documentation page, you need to:
Click the dropdown arrow (an input element)
Click the cell that has the text you want (a td element)
In your case, it would look like:
##ie.input(:class => 'dijitArrowButtonInner').click
##ie.td(:class => 'dijitMenuItemLabel', :text => /Account1/i).click
Here is a working example (though it relies on the dijit css files still being available online).
require 'watir-webdriver'
browser = Watir::Browser.new
browser.goto "data:text/html,#{DATA.read}"
browser.input(:class => 'dijitArrowButtonInner').click
browser.td(:class => 'dijitMenuItemLabel', :text => 'Arizona').click
sleep(10) # Just so that you can see the dropdown has changed
browser.close
__END__
<html>
<head>
<link rel="stylesheet" href="https://dojotoolkit.org/reference-guide/1.9/_static/js/dijit/themes/claro/claro.css">
<script>dojoConfig = {async: true, parseOnLoad: true}</script>
<script src="https://dojotoolkit.org/reference-guide/1.9/_static/js/dojo/dojo.js"></script>
<script>require(["dojo/parser", "dijit/form/Select"]);</script>
</head>
<body class="claro">
<div name="select3" value="AL" data-dojo-type="dijit/form/Select">
<span value="AL"><b>Alabama</b></span>
<span value="AZ"><i>Arizona</i></span>
</div>
</body>
</html>
Watir-Classic
The above solution works for watir-webdriver, but not watir-classic. Clicking the dropdown (actually a table) is not triggering sufficient events to open the dropdown. As a work around, it seems you can use send_keys to trigger the right events.
Assuming that browser is opened to a page with the above html, the following will work:
browser.table(:id => 'dijit_form_Select_0').send_keys :enter
browser.td(:class => 'dijitMenuItemLabel', :text => 'Arizona').click
Note that the table in this code is the selected option (when the dropdown is closed).

Resources