I am doing many tests, where I have to put values into 168 inputs fields in a table. At this moment, I am using for statement like this:
for (int i = 1; i < numberOfValues + 1; i++) {
try {
findingElement.byXPath(".//*[#id='TDCON']/tbody/tr[" + i + "]/td[4]/span/span[2]/span/span/input").sendKeys(Keys.chord(Keys.CONTROL, "a"), value);
}catch (NoSuchElementException ex) {
break;
}
}
It took ages to execute 40 tests similar to this. Is there any faster way using Selenium WebDriver?
The time of execution is proportional to the number of commands executed. So to reduce it, you could select all the elements with a single call. You should also use a CSS selector rather than an XPath when it's possible:
List<WebElement> elements = driver.findElements(By.cssSelector(
"#TDCON > tbody > tr > td:nth-child(4) > span > span:nth-child(2) > span > span > input"));
for (int i = 0; i < numberOfValues; i++) {
try {
elements[i].sendKeys(Keys.chord(Keys.CONTROL, "a"), value);
}catch (NoSuchElementException ex) {
break;
}
}
Another way would be to inject a piece of Javascript and direcly assign the .value property:
((JavascriptExecutor)driver).executeScript(
"var cells = arguments[0].querySelectorAll('#TDCON > tbody > tr > td:nth-child(4)'); " +
"var values = arguments[1]; " +
"for(var i = 0; i < values.length; ++i) { " +
" cells[i].querySelector('span > span:nth-child(2) > span > span > input').value = values[i]; " +
"} "
, findElement, values);
But it might not work if the typing is handled dynamically by the page.
Related
I am trying to select all checkboxes whose value is matched to my value.
Code is working fine when the web page has no vertical scroll. But if web page has some more data then the checkbox is not selected as I want.
Here is my code-
List<WebElement> rselect = tagdis1.findElements(By.className("row-selection-checkbox"));
System.out.println("Row selection Size- " + rselect.size());
List<WebElement> record = driver.findElements(By.id("$ctrl.item.id"));
System.out.println("Size- " + record.size());
int DocNameCount = 0;
for (int j = 0; j < record.size(); j++) {
String Pname = record.get(j).getText();
System.out.println("Pdf name- " + Pname);
if (Pname.equals(docName + ".pdf")) {
// here total 4 records i get but able to click only on 3 records
System.out.println(j + " " + Pname);
rselect.get(j).click();
Thread.sleep(2000);
}
}
Please use scroll option in your operation,
/*
* By
* scroll to the element and wait
*/
public void scroll(By element){
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].scrollIntoView(true);",driver.findElement(element));
log.info("Scrolling down");
}
My table has tagName "td" and "mat-cell". I have implement source as below sample that just get the value of the cell that has tagName is "td".
How to I got data that included tagName is "td" or "mat-cell"?
WebElement table = driver.findElement(taskListTablexpath);
List<WebElement> rows = table.findElements(By.tagName("tr"));
int row_count = rows.size();
System.out.println("Total Row: " + row_count);
for (int row = 0; row < row_count; row = row + 2) {
**List<WebElement> columns = rows.get(row).findElements(By.tagName("td"));**
int columns_count = columns.size();
System.out.println("Number of cells In Row " + row + " are " + columns_count);
for (int column = 0; column < columns_count; column++) {
String celtext = columns.get(column).getText();
if (celtext == null)
continue;
System.out
.println("Cell Value of row number " + row + " and column number " + column + " Is " + celtext);
}
System.out.println("-------------------------------------------------- ");
}
}
There can be only one tag, if you want to match <td> elements which have mat-cell class attribute - you need to amend your selector to be something like:
./td[contains(#class,'mat-cell')]
More information:
XPath Tutorial
XPath Axes
XPath Operators & Functions
Also be aware of Table class available via HtmlElements framework, it makes working with Tables inlcuding Angular Material tables much easier
findElements(By.Xpath(".//td | .//mat-cell"))
There is a dropdown list where each selection has a different URL under the dropdown buttons. Suppose when I select first option then it shows 10 hyperlink and select the second option it shows 5 hyperlinks, etc.
Problem - When I select the second option, it is still showing 10 hyperlinks instead of 5 and shows
org.openqa.selenium.StaleElementReferenceException: Element not found
in the cache - perhaps the page has changed since it was looked up
Select select = new Select(selectdropdown);
List<WebElement> options = select.getOptions();
int isize = options.size();
for (int i = 0; i < isize; i++)
{
String value = select.getOptions().get(i).getText();
driver.manage().timeouts().implicitlyWait(100, TimeUnit.SECONDS);
WebElement WebElementer = driver.findElement(By.xpath("//*[#id='content-inner']"));
List<WebElement> elementList = new ArrayList<>();
elementList = WebElementer.findElements(By.cssSelector("a[href]"));
System.out.println("Total number of links found" + elementList.size());
System.out.println("to check wheather link is working or not");
for (WebElement element : elementList)
{
try
{
System.out.println("URL: " + element.getAttribute("href").trim() + " returned "
+ islinkBroken(new URL(element.getAttribute("href").trim())));
}
catch (Exception exp)
{
System.out.println("At " + element.getAttribute("innerHTML")
+ " Exception occured -> " + exp.getMessage());
}
}
}
where you selecting the element ?? (C# syntax example)
IList<IWebElement> accountsDDL = driver.FindElements(By.XPath("//select[#id='yourSelectId']/option"));
for (int i = 1; i < accountsDDL.Count; i++)
{
new SelectElement(driver.FindElement(By.Name("yourSelectId"))).SelectByText(accountsDDL[i].Text); // Selecting the element
}
In java
I spent a little time cleaning up your code and added a few things. See if this works. As Leon said, I think one of the issues was that you didn't have code that actually changed the selected option.
Select select = new Select(selectdropdown);
for (int i = 0; i < select.getOptions().size(); i++)
{
select.selectByIndex(i); // you were missing this line?
// String value = select.getFirstSelectedOption().getText(); // this variable is never used
// driver.manage().timeouts().implicitlyWait(100, TimeUnit.SECONDS); // this doesn't do what you think it does
// I think this next line should work. I combined the two locators into one.
List<WebElement> elementList = driver.findElements(By.cssSelector("#content-inner a[href]"));
System.out.println("Total number of links found" + elementList.size());
System.out.println("to check wheather link is working or not");
for (WebElement element : elementList)
{
try
{
String href = element.getAttribute("href").trim();
System.out.println("URL: " + href + " returned " + islinkBroken(new URL(href)));
}
catch (Exception exp)
{
System.out.println("At " + element.getAttribute("innerHTML") + " Exception occured -> " + exp.getMessage());
}
}
}
Suggestion: It might be useful to you to add the selected option text to your exception message.
im currently having a problem in getting the headers title of a table to make a validation, it work great until column 6, because when it goes to next one which isn't visible the .getText() is blank. I no the xpath is correct.
public void getAndSaveDataOfTable (final String tabla) throws FileNotFoundException{
WebElement element = driver.findElement(By.xpath(tabla));
List<WebElement> elements = element.findElements(By.xpath("th"));
Assert.assertTrue(elements.size() > 1);
int cantelements = elements.size();
for (int i = 1; i <= cantelements; i++) {
String data = driver.findElement(
By.xpath(".//div[#class='ui-datatable-scrollable-header-box']//table/thead/tr/th["+ i + "]/span[1]")).getText();
System.out.println("EL nombre del encabezado " + i + " " + data);
datosFila.put(i, data);
}
So between column 7and 20 I can't get the text of the header.
If you are going to be using the JavascriptExecutor several times (you said your issue is on multiple columns 7-20) I would suggest you can optimize by running JS only once and then iterating through in Java, rather than running JS again for every operation. The JavascriptExecutor is slow, and you'll save whole seconds on the total test time by avoiding even 12+ extra JS executions.
// JavaScript to get text from tHeads
String getTheadTexts =
"var tHeads = []; " +
"for (i = o; i < 20; i++) { " +
"var cssSelector = 'div.ui-datatable-scrollable-header-box table thead tr th' + i + ' span:nth-of-type(1)'; " +
"var elem = document.querySelector(cssSelector); " +
"var elemText = ''; " +
"if ((elem.textContent) && (typeof (elem.textContent) != 'undefined')) { " +
"tHeads.push(elem.textContent); " +
"} else { " +
"tHeads.push(elem.innerText); " +
"} " +
"} " +
"return tHeads; ";
// Execute the JS to populate a List
List<String> tHeadTexts = (ArrayList<String>) js.executeScript(getTheadTexts);
// Do some operation on each List item
int i = 0;
for (String data: tHeadTexts){
System.out.println("EL nombre del encabezado " + i + " " + data);
datosFila.put(i, data);
i++;
}
I ran into what sounds like what you're running into. Take a look at my post on
WebElement getText() is an empty string in Firefox if element is not physically visible on the screen
I ended up solving it by using a little bit of JavaScript to columns "into view". Hopefully this helps you out.
private void scrollToElement(WebElement element){
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
}
I am testing an application with a lot of tables. each cell in the table contains a variety of things that i may need, such as the id to input text, id for a drop down, checkboxes, and so forth.
I am using a solution I found here, but I have so many elements it bogs this down and on a table that has 5 rows and 21 columns it takes at least 120 seconds to obtain all of the data I need.
here is some code I am using
String[] additInfo = {"name", "id", "value"};
String firstClassName = "tableClassName";
String cssSelector = "tbody tr";
String additInfoName = additInfo[0];
int rowNum, colNum;
rowNum = 0;
WebElement table = driver.findElement(By.className(firstClassName));
List<WebElement> row = table.findElements(By.cssSelector(cssSelector));
print.ln("# of rows: " + row.size());
for (WebElement rowElement : row) {
System.out.println("get row elms");
List<WebElement> column = rowElement.findElements(By.tagName("td"));
System.out.println("number of col: " + column.size());
colNum = 0;
for (WebElement colElement : column) {
String tableText = colElement.getText();
System.out.println("row # " + rowNum + ", col # " + colNum + " text: " + tableText);
WebElement nestedElm;
System.out.println("Get additional Info for " + additInfoName);
String infoUnderTag = "class";
nestedElm = colElement.findElement(By.tagName(infoUnderTag));
for (int i = 1; i < additInfo.length; i++) {
String attribute = nestedElm.getAttribute(additInfo[i]);
System.out.println("\t" + additInfo[i] + ": " + attribute);
}
colNum++;
} //end Elements
rowNum++;
} //end rows
Is there any way of speeding this up? I took out some unnecessary findElements commands which doubled the speed, but it is still very slow on those larger tables.
Thanks in advance!
I found a solution for now. I was using IE9 64 bit version. From what I found here the 64 bit version of IE does not have the faster JavaScript engine, only the 32 bit version. I changed my WebDriver to open that IEDriverServer.exe version instead, and it is running 3 or 4 times faster then before. Not nearly as quick as Firefox however.