I have a webtable which has multiple rows. I want to create a loop such that it traverses all the rows of this table and click on column 1 elements of first row, then check inside that an Edit button exists or not. Then come back and click on next element and check the edit button. Then come back and repeat till all rows are traversed.
But in current code implemented by me, it is just traversing the first row and then exiting. Could someone help me with same.
viewDiscussionScope(driver, scope);
WebElement paginationLabel = WaitUtils.waitForElement(driver, By.cssSelector(".v-csslayout-cvr-c-pagination__header"));
if(paginationLabel.isDisplayed())
{
WebElement table = WaitUtils.waitForElement(driver, By.cssSelector("table.eds-o-table.cvr-c-table--list tbody"));
List<WebElement> rows = table.findElements(By.cssSelector("tr.eds-o-table__row"));
for(WebElement row: rows)
{
List<WebElement> tableCols = row.findElements(By.cssSelector("td.eds-o-table__cell:nth-of-type(1)"));
for(WebElement col : tableCols)
{
col.findElement(By.cssSelector(".v-label-eds-c-text--bold")).click();
WebElement messageField = WaitUtils.waitForElement(driver, By.cssSelector(".eds-o-media__body-eds-o-media__body--top .v-label-eds-u-flexitext.v-label-undef-w:nth-of-type(1)"));
String messageText = messageField.getText();
boolean editLabel = (driver.findElement(By.cssSelector(".eds-c-button-set-eds-c-button-set--align-right .v-button-eds-s-is-first")).getText()).equals("Edit");
if(!(editLabel))
{
LOG.info(messageText+" is not editable by the logged in user");
}
else
{
LOG.info(messageText+" is editable by the logged in user");
}
break;
}
break;
}
}
}
Remove break statement from your parent for loop!
for(WebElement row: rows)
{
List<WebElement> tableCols = row.findElements(By.cssSelector("td.eds-o-table__cell:nth-of-type(1)"));
for(WebElement col : tableCols)
{
// your code
}
// REMOVE => break;
}
}
You have 2 break that need to be removed and you don't need to loop through the td if you want to click only first td
if (paginationLabel.isDisplayed())
{
WebElement table = WaitUtils.waitForElement(driver, By.cssSelector("table.eds-o-table.cvr-c-table--list tbody"));
List<WebElement> rows = table.findElements(By.cssSelector("tr.eds-o-table__row"));
for (WebElement row : rows)
{
// get first td
WebElement tableCol = row.findElement(By.cssSelector("td.eds-o-table__cell:nth-of-type(1)"));
tableCol.findElement(By.cssSelector(".v-label-eds-c-text--bold")).click();
WebElement messageField = WaitUtils.waitForElement(driver, By.cssSelector(".eds-o-media__body-eds-o-media__body--top .v-label-eds-u-flexitext.v-label-undef-w:nth-of-type(1)"));
String messageText = messageField.getText();
boolean editLabel = (driver.findElement(By.cssSelector(".eds-c-button-set-eds-c-button-set--align-right .v-button-eds-s-is-first")).getText()).equals("Edit");
if (!(editLabel))
{
LOG.info(messageText + " is not editable by the logged in user");
}
else
{
LOG.info(messageText + " is editable by the logged in user");
}
}
}
first you need to find where is edit button located in table you can find its xpath, does of all edit buttons having same xpath if yes then your problem will be solved in you just need to find by findElements() method and store it into List and to get value of edit buttons or to check if is available or not you can call .get() method which will get all respected buttons of same xpath and by specifying index as .get(0),.get(1) or pass it in loop you get his value by .getText() method and check or perform actions on that
If you could provide the DOM of the table you trying to work on, i can help you better.
If i understood correctly your problem here is the solution, also, i strongly advice to use methods for small tasks, which will help you in the long run. Also, the selectors needs a better wraping, also the explicit wait needs a wrapper with his own methods.
try this:
if (paginationLabel.isDisplayed())
{
WebElement table = WaitUtils.waitForElement(driver, By.cssSelector("table.eds-o-table.cvr-c-table--list tbody"));
List<WebElement> rows = table.findElements(By.cssSelector("tr.eds-o-table__row"));
for (int i=1; i<=rows.size; i++)
{
// get first td
clickColumn(int i);
getMessageText(int i);
boolean editLabel = (driver.findElement(By.cssSelector(".eds-c-button-set-eds-c-button-set--align-right .v-button-eds-s-is-first")).getText()).equals("Edit");
if (!(editLabel))
{
LOG.info(messageText + " is not editable by the logged in user");
}
else
{
LOG.info(messageText + " is editable by the logged in user");
}
}
}
private clickColumn(int position) {
WebElement tableCol = row.findElement(By.cssSelector("td.eds-o-table__cell:nth-of-type(" + position + ")"));
tableCol.findElement(By.cssSelector(".v-label-eds-c-text--bold")).click();
}
private getMessageText(int position) {
WebElement messageField = WaitUtils.waitForElement(driver, By.cssSelector(".eds-o-media__body-eds-o-media__body--top .v-label-eds-u-flexitext.v-label-undef-w:nth-of-type(" + position + ")"));
String messageText = messageField.getText();
}
Related
I am unable to locate dynamic web element location for drop down list
public void selectClassofService(String value) throws InterruptedException
{
driver.findElement(By.xpath("/html/body/div[1]/div/div/div/div[3]/div[2]/div[2]/div/div/div/div[2]/div[2]/div[2]/form/div[5]/div/div[2]/div/div/div[1]/input")).click();
List<WebElement> list = driver.findElements(By.xpath("/html/body/div[1]/div/div/div/div[3]/div[2]/div[2]/div/div/div/div[2]/div[2]/div[2]/form/div[5]/div/div[2]/div/div/div[1]/input"));
System.out.println("Size of the list size =" + list.size());
for (int i = 0; i < list.size(); i++) {
System.out.println("names of the divisions " + list.get(i).getText());
if (list.get(i).getText().contains(value)) {
list.get(i).click();
break;
}
}
this is my sample html code
<ui class="vs_dropdown-menu" role="listbox">
<l1 class=vs_dropdown-option role="option">sample pack </l1>
<l2 class=vs_dropdown-option vs vs_dropdown-option--highlight role="option">sample pack </l2>
<l3 class=vs_dropdown-option role="option">sample pack2 </l3>
First of all, Stop writing too long xpaths. there are better ways to access an element instead of doing that creepy things.
String dropdownXpath = "//input[#class='vs_dropdown-menu' and #role='listbox']";
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath(dropdownXpath))).click();
List<WebElement> myList = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath(dropdownXpath + "//li[#class='vs_dropdown-option' and #role='option']")));
for (WebElement element:myList)
{
System.out.println("names of the divisions " + element.getText());
if(element.getText().contains("Mumbai"));
element.click();
}
if it's not possible to access dropdown like above, just get the parent div's Id like this:
String dropdownXpath = "//div[#id='some-id']input[#class='vs_dropdown-menu' and #role='listbox']";
don't waste your time by crawling html tags to find an element.
I need to get the Select Tag and Input Tag in web table for this I created the below code to get the Tag name in web table.
For this
Created a List of Elements to get the Number of rows in table.
For declare the variable as "i" to looping.
Find the Select tag in each row to sent the inputs in table.if the select tag presence in row pass the input value else pass different value in web table.
// web Table
WebElement table =d.findElement(By.xpath("//*[#id='ui-grid']/div/div/div/div[2]/table/tbody"));
List<WebElement> trcount = table.findElements(By.tagName("tr"));
int size = trcount.size();
System.out.println(size);
//Using size created the for loop to find each row available in table.
for(int i=1;i<size;i++) {
//Declare the Xpath to find the particular row
By tag = By.xpath("(//*[#id='ui-grid']/div/div/div/div[2]/table/tbody/tr/td/span/select)["+i+"]");
By Input_tag = By.xpath("(//*[#id='ui-grid']/div/div/div/div[2]/table/tbody/tr/td/span/input)["+i+"]");
List<WebElement> tdcount = trcount.get(i).findElements(tag);
String tag1 = tdcount.get(i).getTagName();
System.out.println(tag1);
if(tag1.equals("select")){
d.findElement(By.xpath(tag))Select level = new Select(d.FindElement(tag));
level.selectByVisibleText("YES");
}else {
d.findElement(Input_tag).sendKeys("12");
}
}
Expected Result:
If Web table presence Select tab then value selected from dropdown else Input Tag presence value should be passed.
Actual Result:
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
//Get the number of count in web table.
WebElement table =d.findElement(By.xpath("//*[#id='ui-grid']/div/div/div/div[2]/table/tbody"));
List<WebElement> trcount = table.findElements(By.tagName("tr"));
int size = trcount.size();
System.out.println(size);
//Select particular tag(Select tag)
List<WebElement> Select = table.findElements(By.xpath("//*[#id='ui-grid']/div/div/div/div[2]/table/tbody/tr/td/span/select"));
int select_size = Select.size();
System.out.println(select_size);
//If web table have select tag perfrom below else to catch no search elements exceptions.
try{
for(int j=1;j<=select_size;j++) {
By tag = By.xpath("(//*[#class='ng-star-inserted']/span/select)["+j+"]");
System.out.println("Test");
}
}catch(Exception e){
System.out.println((e.getMessage()));
}
//Select particular tag(Input tag)
List<WebElement> Select1 = table.findElements(By.xpath("//*[#id='ui-grid']/div/div/div/div[2]/table/tbody/tr/td/span/input"));
int select_input = Select1.size();
System.out.println(select_input);
try{
for(int i=1;i<=select_input;i++) {
By tag1 = By.xpath("(//*[#class='ng-star-inserted']/span/input)["+i+"]");
System.out.println("Test");
d.findElement(tag1).sendKeys("12345");
Thread.sleep(3000);
//d.findElement(Accept_button).click();
}
}catch(Exception e){
System.out.println((e.getMessage()));
}
I want to know how to nest dropdowns using selenium webdriver using java,i.e., I have 2 dropdowns and can these dropdowns be nested one after the other?
After looping 2 times for a dropdown it is showing stale element reference error
I have written the following code:
Select drpdwns6 = new Select(driver.findElement(By.xpath("//*[#id=\"MainContent_ddlBillable\"]")));
List <WebElement> sels6 = drpdwns6.getOptions();
sels6.size();
for(int s6=0;s6<sels6.size();s6++) {
drpdwns6.selectByIndex(s6);
System.out.println("selected value"+s6);
Select drpdwns7 = new Select(driver.findElement(By.xpath("//*[#id=\"MainContent_ddlofflinestatus\"]")));
List <WebElement> sels7 = drpdwns7.getOptions();
sels7.size();
for(int s7=0;s7<sels7.size();s7++) {
drpdwns7.selectByIndex(s7);
System.out.println("selected value"+s7);
}
}
My guess is selecting the option from the dropdown refreshes the DOM, so the exception is thrown. You need to relocate the dropdown in each itreation
Select drpdwns6 = new Select(driver.findElement(By.id("MainContent_ddlBillable")));
int drpdwns6Size = drpdwns6.getOptions().size();
for(int s6 = 0 ; s6 < drpdwns6Size ; s6++) {
drpdwns6 = new Select(driver.findElement(By.id("MainContent_ddlBillable")));
drpdwns6.selectByIndex(s6);
System.out.println("selected value"+s6);
Select drpdwns7 = new Select(driver.findElement(By.id("MainContent_ddlofflinestatus")));
int drpdwns7Size = drpdwns7.getOptions().size();
for(int s7 = 0 ; drpdwns7Size ; s7++) {
drpdwns7 = new Select(driver.findElement(By.id("MainContent_ddlofflinestatus")));
drpdwns7.selectByIndex(s7);
System.out.println("selected value"+s7);
}
}
As a side note, if you have an id use By.id it instead of By.xpath
You get the Stale element exception whenever the element present in the DOM is deleted or removed or is not available.
The above answer (ie) relocating the element once the DOM is refreshed or you could use Webdriver wait, If an element is not attached to DOM then you could try using ‘try-catch block’ within ‘for loop’ like below
driver.manage().timeouts().implicitlywait(30,TimeUnit.SECONDS);
try{
Select drpdwns6 = new
Select(driver.findElementByXpath("//[#id=\"MainContent_ddlBillable\"]")));
List <WebElement> sels6AllOptions = drpdwns6.getOptions();
int count1=sels6AllOptions.size();
for(int s6=0;s6<count1;s6++)
{
drpdwns6.selectByIndex(s6);
}
}
catch(StaleElementException e1){
System.out.println("selected value"+s6);
}
try{
Select drpdwns7 = new Select(driver.findElement(By.xpath("//*[#id=\"MainContent_ddlofflinestatus\"]")));
List <WebElement> sels7AllOptions = drpdwns7.getOptions();
int count2=sels7AllOptions.size();
for(int s7=0;s7<count2;s7++) {
drpdwns7.selectByIndex(s7);
catch(StaleElementException e2){
System.out.println("selected value"+s7);
}
}
I try to retrieve text via foreach loop,as according to page wise. Flow is : It prints text of single row and as soon as it completes, it goes to second page and start again to retrieve text. Problem is, it retrieves data of first page multiple times like sometimes 2 or 3 or 4 times, How to control it for single time execution ?
if (driver.findElement(By.xpath("//button[#ng-click='currentPage=currentPage+1']")).isEnabled()) {
int ilength = driver.findElements(By.xpath("//input[#ng-attr-id='{{item.attr}}']")).size();
Outer: for (int i1 = ilength; i1 > 0;) {
List<WebElement> findData = driver.findElements(By.xpath("//input[#ng-attr-id='{{item.attr}}']"));
for (WebElement webElement : findData) {
String printGroupName = webElement.getAttribute("value").toString();
System.out.println(printGroupName);
ilength--;
}
if (driver.findElement(By.xpath("//button[#ng-click='currentPage=currentPage+1']")).isEnabled()) {
action.moveToElement(driver.findElement(By.xpath("//button[#ng-click='currentPage=currentPage+1']"))).click().perform();
page.pagecallingUtility();
ilength = driver.findElements(By.xpath("//input[#ng-attr-id='{{item.attr}}']")).size();
} else {
break Outer;
}
}
} else {
List<WebElement> findAllGroupName = driver.findElements(By.xpath("//input[#ng-attr-id='{{item.attr}}']"));
for (WebElement webElement : findAllGroupName) {
String printGroupName = webElement.getAttribute("value").toString();
System.out.println(printGroupName);
}
}
Console Data, on which it retrieve information
Your loop can be simplified as below.
boolean newPageOpened = true;
while (newPageOpened) {
List<WebElement> findData = driver.findElements(By.xpath("//input[#ng-attr-id='{{item.attr}}']"));
for (WebElement webElement : findData) {
if (webElement.isDisplayed()) {
String printGroupName = webElement.getAttribute("value").toString();
System.out.println(printGroupName);
}
}
WebElement nextButton = driver.findElement(By.xpath("//button[#ng-click='currentPage=currentPage+1']"));
if (nextButton.isEnabled()) {
action.moveToElement(nextButton).click().perform();
page.pagecallingUtility();
} else {
newPageOpened = false;
}
}
As for the contents of the fist page printing again and again, I suspect when you open the second page the contents of the first page are simply hidden in the page. So when you use driver.findElements(By.xpath("//input[#ng-attr-id='{{item.attr}}']")) the hidden first page elements are also found. The simple solution is to check if the element is displayed before printing it.
Here is a code fragment:
System.setProperty(Constants.WEBDRIVER_CHROME_DRIVER_PROP, Constants.WEBDRIVER_CHROME_DRIVER_PATH);
m_chromeWebdriver = new ChromeDriver();
m_chromeWebdriver.get("mysite.org");
WebElement arrowElement = m_chromeWebdriver.findElement(By.cssSelector(_ARROW_NEXT_DAY));
arrowElement.click();
WebElement elmMainTable = m_chromeWebdriver.findElement(By.className("table-main"));
List<WebElement> allRows = elmMainTable.findElements(By.tagName("tr"));
for (WebElement row : allRows) {
List<WebElement> cells = row.findElements(By.tagName("td"));
for (WebElement cell : cells) {
System.out.println(cell.getText());
}
}
m_chromeWebdriver.quit();
At the last line I get an
"stale element reference: element is not attached to the page
document"
exception.
Why and how can I solve that?
I use Chromdriver 2.2.9.
Well, as this is probably not the perfect solution - at least it worked for me...
I put all the relevant code into a method like this:
private static void handleTable() {
for (int i = 1; i < 5; i++) {
try {
WebElement elmMainTable = m_chromeWebdriver.findElement(By.className("table-main"));
List<WebElement> allRows = elmMainTable.findElements(By.cssSelector(".table-main tr"));
for (WebElement row : allRows) {
List<WebElement> cells = row.findElements(By.tagName("td"));
for (WebElement cell : cells) {
System.out.print(cell.getText() + "\t");
}
System.out.println();
}
} catch (StaleElementReferenceException e) {
//e.printStackTrace();
handleTable();
}
return;
}
}
And it worked! You can change the value 5 to which ever you'd like of course.
I learned the main reason for Selenium stale exception is element changed in DOM. In case, the stale exception are caused by those web elements you are not handling, you can try below try-catch and continue method in JAVA.
//get webelement list of button on the OU tab
List<WebElement> ouList =
Logon.wDriver.findElements(By.tagName(PagePropertise.tagButton));
// it should be 6
System.out.println("List Size is: "+ouList.size());
for (int i=0; i<ouList.size(); i++ ) {
//get each button element to verify with input Org name
WebElement ouName= ouList.get(i);
String ouLabel = null;
try {
ouLabel = ouName.getText();
} catch (StaleElementReferenceException e) {
//handle in exception catch, just skip invalid element and continue for to handle rest of loop
System.out.println("WebElement "+i+" = text "+ ouLabel);
continue;
}
System.out.println("WebElement "+i+" = text "+ ouLabel);
//webelement processing
...
//for some reason some of webelements in the OUlist were changed for above processing code.
}